diff --git a/.travis.yml b/.travis.yml index a17e360c40..8dea1c96a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +dist: precise language: php php: - 5.5 @@ -51,11 +52,11 @@ before_install: - make -j3 - sudo make install && sudo ldconfig - cd ../.. - - sudo mv /etc/apt/sources.list.d/pgdg-source.list* /tmp - - sudo apt-get remove postgis libpq5 libpq-dev postgresql-9.1-postgis postgresql-9.2-postgis postgresql-9.3-postgis postgresql-9.1 postgresql-9.2 postgresql-9.3 libgdal1 + - sudo mv /etc/apt/sources.list.d/pgdg* /tmp + - sudo apt-get remove postgis libpq5 libpq-dev postgresql-9.1-postgis postgresql-9.1-postgis-2.2-scripts postgresql-9.2-postgis postgresql-9.3-postgis postgresql-9.1 postgresql-9.2 postgresql-9.3 - sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable - sudo apt-get update - - sudo apt-get install bison flex python-lxml libfribidi-dev swig cmake librsvg2-dev colordiff postgis postgresql-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev libgeos-dev libgd2-xpm-dev libfreetype6-dev libfcgi-dev libcurl4-gnutls-dev libcairo2-dev libgdal1-dev libproj-dev libxml2-dev python-dev php5-dev libexempi-dev lcov lftp + - sudo apt-get install bison flex python-lxml libfribidi-dev swig cmake librsvg2-dev colordiff postgis postgresql-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev libgeos-dev libgd2-xpm-dev libfreetype6-dev libfcgi-dev libcurl4-gnutls-dev libcairo2-dev libgdal1-dev libproj-dev libxml2-dev python-dev php5-dev libexempi-dev lcov lftp libgdal-dev libgdal1h - sudo pip install git+git://github.com/tbonfort/cpp-coveralls.git@extensions - cd msautotest - ./create_postgis_test_data.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 3788c1a6f2..5dedf0bf43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ include(CheckCSourceCompiles) set (MapServer_VERSION_MAJOR 7) set (MapServer_VERSION_MINOR 0) -set (MapServer_VERSION_REVISION 1) +set (MapServer_VERSION_REVISION 8) set (MapServer_VERSION_SUFFIX "") set(TARGET_VERSION_MAJOR ${MapServer_VERSION_MAJOR}) @@ -857,7 +857,7 @@ ms_link_libraries( ${CMAKE_DL_LIBS} m ) endif(UNIX) if (WIN32) -ms_link_libraries( ${MS_EXTERNAL_LIBS}) +ms_link_libraries( ${MS_EXTERNAL_LIBS} ws2_32.lib) endif (WIN32) configure_file ( diff --git a/HISTORY.TXT b/HISTORY.TXT index 7ddb075ed4..26a49f6898 100644 --- a/HISTORY.TXT +++ b/HISTORY.TXT @@ -8,7 +8,15 @@ next. Developers are strongly encouraged to document their changes and their impacts on the users here. (Please add the most recent changes to the top of the list.) -For a complete change history, please see the Git log comments. +For a complete change history, please see the Git log comments. For more +details about recent point releases, please see the online changelog at: +http://mapserver.org/development/changelog/ + +7.0.8 release (2021-4-30) +------------------------- + +- Security release, see ticket #6313 for more information. +- Improve setting of key environment vars for FastCGI/IIS, see ticket #6289. 7.0.0 release (2015/07/24) -------------------------- @@ -1628,7 +1636,7 @@ Version 5.4.0-beta1 (2009-2-18): - Fixed a scalebar rounding problem causing to draw zero scalebar width (#2890) -- SLD: if it conatins a Filer Encoding tag, try to always set the +- SLD: if it contains a Filter Encoding tag, try to always set the layer's FILTER element (#2889) - Add support for rendering INLINE layers with layer attributes (items) (#2870) diff --git a/README b/README index 416d414c90..668aeb9c11 100644 --- a/README +++ b/README @@ -67,7 +67,8 @@ License :: - Copyright (c) 1996-2007 Regents of the University of Minnesota. + Copyright (c) 2008-2018 Open Source Geospatial Foundation. + Copyright (c) 1996-2008 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.WIN32 b/README.WIN32 index dedf7042c1..d7d760f641 100644 --- a/README.WIN32 +++ b/README.WIN32 @@ -9,7 +9,7 @@ IMPORTANT - READ THIS FIRST: So it is strongly recommended that you use one of the precompiled binaries available on the MapServer site: - http://mapserver.gis.umn.edu/download/current/windows + http://www.mapserver.org/download.html#windows There are precompiled Win32 binaries available for the last stable release and the latest nightly build and they include the most common @@ -22,40 +22,108 @@ IMPORTANT - READ THIS FIRST: -------------------------------------------------------------------- -For the developers using MSVC++, a NMAKE makefile (Makefile.vc + nmake.opt) -to build the MapServer library and executable programs is included with -the distribution. +The easyest way to build Mapserver on Windows on your own is to use the +build-system from http://gisinternals.com/. +GISInternals provide a complete set of sources and dependencies and even +makefiles for the full version of Visual Studio (not Express oder Community). +You don't have to download and compile them all by your own. + +If you are not using full version of Visual Studio you can not use the makefiles +from GISInternals but you can still use the downloads to make your life easier. + +Building with the full version of Visual Studio is easy. +Download the SDK for you version and follow the readme inside the packages. + +This Readme will cover the compilation with Visual Studio 2012 Express on +Windows with CMake and the GISInternals-Packages for the following reasons: + - not everybody wants to buy Visual Studio and there is no reason to force + you to buy it just tu build Mapserver on Windows + - CMake is the configuration-system for Linux. Why should you use something + else which needs to be maintainerd? + - as of today, PHP-Mapscript is not suppored for PHP-7. PHP-5.6 is build + with VC11. To make PHP-Mapscript compatible with the downloadable + PHP-Version you need to build with VC11 wich is Visual Studio 2012. + - GISInternals Downloads contain most dependencies. it's way easier + +If you want to compile Mapserver with any other version of Visual Studio you +can for sure use this documentation as help but maybe, some things here won't +work for you. -To build the package using the Makefile.vc and NMAKE: +-------------------------------------------------------------------- + Prerequisites +-------------------------------------------------------------------- + +To build Mapserver on Windows with Visual Studio 2012 Express you need +Visual Studio 2012 Express installed. +Install CMake (https://cmake.org/) and add CMake bin-directory to your PATH +environment variable. You can even to this after opening VS2012 x86 Native +Tools Command Prompt by entering: + set PATH=%PATH%;"C:\Program Files\CMake\bin" +... if CMake is installed to "C:\Program Files\CMake" ;) - - Edit nmake.opt to select (or deselect) optional components of - the MapServer. Please read the notes below about each component - before you move ahead with the compilation. +-------------------------------------------------------------------- + Downloading dependencies +-------------------------------------------------------------------- - - Open a DOS prompt window +For our first build, we will use stable releases to build mapserver. +Download MSVC 2012 win32 Packages for GDAL-2.1.2 and Mapserver-7.0.2 from http://gisinternals.com/release.php. +We need "Compiled binaries in a single .zip package", "GDAL and MapServer sources" and "Compiled libraries and headers". +Download the MSVC 2012 win32 Developement Kit from http://gisinternals.com/sdk.php. +Extract everything to C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2. +There should be the directories inside now: bin, doc, gdal, include, lib, regex-0.12, relase-1700, ... +After you got this done, feel free to use other packages which fit your needs better. - - Run the VCVARS32.BAT script to initialize the VC++ environment - variables. VCVARS32.BAT is automatically generated by the MSVC++ - install procedure and should be located in the BIN sub-directory of - your MSVC++ installation. +-------------------------------------------------------------------- + Mapserver-sources +-------------------------------------------------------------------- - - Then start the build with: - nmake /f Makefile.vc +Download at least Mapserver-7.0.3 or current 7.0-Branch from github +and extract or clone from github to C:\dev\work\mapserver. -This will create "mapserv.exe" (the main MapServer CGI program), the -other command-line utilities, "mapserver.lib" and "libmap.dll" that is -used by theMapScript modules. +-------------------------------------------------------------------- + Building Mapserver +-------------------------------------------------------------------- +After downloading and extracting everything, to build Mapserver, follow this steps: +1. Open VS2012 x86 Native Tools Command Prompt (i'm german, hope it is translated +correctly). +2. Add CMake-bin to your PATH: + set PATH=%PATH%;"C:\Program Files\CMake\bin" +3. Create build-Directory: + mkdir C:\dev\work\mapserver\build + cd C:\dev\work\mapserver\build +4. Configure: + cmake .. -G "NMake Makefiles" -DBUILD_SHARED_LIBS=1 -DCMAKE_BUILD_TYPE=Release -Wno-dev + cmake .. -DCMAKE_PREFIX_PATH=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2;C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\bin;C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\lib;C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\include + cmake .. -DREGEX_DIR=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\regex-0.12 + cmake .. -DWITH_POSTGIS=0 -DWITH_SOS=1 -DWITH_KML=1 + cmake .. -DWITH_CLIENT_WMS=1 -DWITH_CLIENT_WFS=1 + cmake .. -DWITH_THREAD_SAFETY=1 -DWITH_FCGI=1 + cmake .. -DWITH_CAIRO=1 -DCAIRO_LIBRARY=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\lib\cairo.lib + cmake .. -DWITH_SVGCAIRO=1 -DSVGCAIRO_LIBRARY=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\lib\libsvg-cairo.lib + cmake .. -DSVG_LIBRARY=1 -DSVG_LIBRARY=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\lib\libsvg.lib +5. build + nmake + +Thats it. +You can use all CMake parameters and options as you are used from CMake to fit mapserver to your needs from here. +Enjoy! -------------------------------------------------------------------- MapScript -------------------------------------------------------------------- To compile the various versions of MapScript (Perl, PHP, etc) first compile -the main mapserver directory and then see the README files in the -mapscript/perl, mapscript/php3 or mapscript/python directory for specific +the main mapserver directory and then see the README files in the +mapscript/perl, mapscript/php or mapscript/python directory for specific instructions. +-------------------------------------------------------------------- + Dependencies Part 2 +-------------------------------------------------------------------- + +The following sections descripe how to get mapserver dependencies when not +downloading GISInternals packages. -------------------------------------------------------------------- GD library @@ -168,27 +236,6 @@ instructions. with the PNG support, make sure that the libpng that you use in mapserver is the same as the one used in GDAL. ------------------------------------------------------------- - Notes on PDF suuport ------------------------------------------------------------- - -The PDF support allows the output of a map file as a PDF file. - -To be able to build mapserver with the PDF support, you need to download -and build a PDF library from www.pdflib.com (http://www.pdflib.com/pdflib/download/index.html). -The best option is to download the zip file containing the source code and build it. Please refer to the docs inside the zip for informations on how to build the library. Here are some quick notes that can help in building mapserver with PDF : - - 1) Build the PDF lib - - - open the project PDFLib.dsw - - build the project pdflib_dll - - after a sucessful build, you should have a pdflib.lib and pdblib.dll under the - pdflib directory - - copy the pdflib.dll under your system directory (ex : c:/winnt/system32) - - 2) Build mapserver with PDF - - - uncomment in the nmake.opt the flags related to PDF $Id$ diff --git a/appveyor.yml b/appveyor.yml index 62b072fa26..53aad8d6eb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -47,7 +47,7 @@ build_script: - 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 -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% -DWITH_CSHARP=1 - cmake --build . --config Release test_script: diff --git a/cmake/FindICONV.cmake b/cmake/FindICONV.cmake index fe83fd3c10..2e36b644ef 100644 --- a/cmake/FindICONV.cmake +++ b/cmake/FindICONV.cmake @@ -48,7 +48,7 @@ if(WIN32) find_file(ICONV_DLL NAMES ${ICONV_DLL_NAMES} PATHS ENV PATH - NO_DEFAULT_PATH) + ${ICONV_INCLUDE_DIR}/../bin) find_file(ICONV_DLL_HELP NAMES ${ICONV_DLL_NAMES} PATHS ENV PATH diff --git a/cmake/FindPHP5.cmake b/cmake/FindPHP5.cmake index eeca42cbe1..4b77f44e72 100644 --- a/cmake/FindPHP5.cmake +++ b/cmake/FindPHP5.cmake @@ -17,22 +17,31 @@ SET(PHP5_POSSIBLE_INCLUDE_PATHS /usr/include/php /usr/local/include/php /usr/local/apache/php + ${PHP5_INCLUDES} ) SET(PHP5_POSSIBLE_LIB_PATHS /usr/lib +if(WIN32) + ${PHP5_INCLUDES}/Release_TS +endif(WIN32) ) -#FIND_PATH(PHP5_FOUND_INCLUDE_PATH main/php.h -# ${PHP5_POSSIBLE_INCLUDE_PATHS}) -# -#IF(PHP5_FOUND_INCLUDE_PATH) -# SET(php5_paths "${PHP5_POSSIBLE_INCLUDE_PATHS}") -# FOREACH(php5_path Zend main TSRM) -# SET(php5_paths ${php5_paths} "${PHP5_FOUND_INCLUDE_PATH}/${php5_path}") -# ENDFOREACH(php5_path Zend main TSRM) -# SET(PHP5_INCLUDE_PATH "${php5_paths}" INTERNAL "PHP5 include paths") -#ENDIF(PHP5_FOUND_INCLUDE_PATH) +find_library(PHP5_LIBRARY + NAMES php5ts.lib + PATHS /sw /opt/local ${PHP5_INCLUDES}/Release_TS +) + +FIND_PATH(PHP5_FOUND_INCLUDE_PATH main/php.h + ${PHP5_POSSIBLE_INCLUDE_PATHS}) + +IF(PHP5_FOUND_INCLUDE_PATH) + SET(php5_paths "${PHP5_POSSIBLE_INCLUDE_PATHS}") + FOREACH(php5_path Zend main TSRM) + SET(php5_paths ${php5_paths} "${PHP5_FOUND_INCLUDE_PATH}/${php5_path}") + ENDFOREACH(php5_path Zend main TSRM) + SET(PHP5_INCLUDE_PATH "${php5_paths}" INTERNAL "PHP5 include paths") +ENDIF(PHP5_FOUND_INCLUDE_PATH) FIND_PROGRAM(PHP5_EXECUTABLE NAMES php5 php @@ -77,6 +86,10 @@ IF(PHP5_CONFIG_EXECUTABLE) MESSAGE(STATUS ${PHP5_MAIN_INCLUDE_DIR}) + IF(NOT PHP5_INCLUDE_PATH) + set(PHP5_INCLUDE_PATH ${PHP5_INCLUDES}) + ENDIF(NOT PHP5_INCLUDE_PATH) + IF(PHP5_VERSION LESS 5) MESSAGE(FATAL_ERROR "PHP version is not 5 or later") ENDIF(PHP5_VERSION LESS 5) diff --git a/fontcache.c b/fontcache.c index a6eace565f..b41e087500 100644 --- a/fontcache.c +++ b/fontcache.c @@ -273,12 +273,18 @@ outline_element* msGetGlyphOutline(face_element *face, glyph_element *glyph) { key.glyph = glyph; UT_HASH_FIND(hh,face->outline_cache,&key, sizeof(outline_element_key),oc); if(!oc) { + FT_Matrix matrix; + FT_Vector pen; FT_Error error; oc = msSmallMalloc(sizeof(outline_element)); if(MS_NINT(glyph->key.size * 96.0/72.0) != face->face->size->metrics.x_ppem) { FT_Set_Pixel_Sizes(face->face,0,MS_NINT(glyph->key.size * 96/72.0)); } - error = FT_Load_Glyph(face->face,glyph->key.codepoint,FT_LOAD_DEFAULT/*|FT_LOAD_IGNORE_TRANSFORM*/|FT_LOAD_NO_HINTING|FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + matrix.xx = matrix.yy = 0x10000L; + matrix.xy = matrix.yx = 0x00000L; + pen.x = pen.y = 0; + FT_Set_Transform(face->face, &matrix, &pen); + error = FT_Load_Glyph(face->face,glyph->key.codepoint,FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP/*|FT_LOAD_IGNORE_TRANSFORM*/|FT_LOAD_NO_HINTING|FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); if(error) { msSetError(MS_MISCERR, "unable to load glyph %ud for font \"%s\"", "msGetGlyphByIndex()",glyph->key.codepoint, face->font); return NULL; diff --git a/hittest.c b/hittest.c index 073442c47c..bec7cb71ff 100644 --- a/hittest.c +++ b/hittest.c @@ -189,10 +189,16 @@ int msHitTestLayer(mapObj *map, layerObj *layer, layer_hittest *hittest) { status = msLayerWhichShapes(layer, searchrect, MS_FALSE); if(status == MS_DONE) { /* no overlap */ +#ifdef USE_GEOS + msFreeShape(&searchpoly); +#endif msLayerClose(layer); hittest->status = 0; return MS_SUCCESS; } else if(status != MS_SUCCESS) { +#ifdef USE_GEOS + msFreeShape(&searchpoly); +#endif msLayerClose(layer); return MS_FAILURE; } @@ -245,6 +251,7 @@ int msHitTestLayer(mapObj *map, layerObj *layer, layer_hittest *hittest) { hittest->status = 1; if(maxfeatures >=0 && featuresdrawn >= maxfeatures) { + msFreeShape(&shape); status = MS_DONE; break; } @@ -258,6 +265,10 @@ int msHitTestLayer(mapObj *map, layerObj *layer, layer_hittest *hittest) { msFreeShape(&shape); } +#ifdef USE_GEOS + msFreeShape(&searchpoly); +#endif + if (classgroup) msFree(classgroup); diff --git a/kerneldensity.c b/kerneldensity.c index bc65a5061f..93a3a9edce 100644 --- a/kerneldensity.c +++ b/kerneldensity.c @@ -318,6 +318,7 @@ int msComputeKernelDensityDataset(mapObj *map, imageObj *image, layerObj *kernel msSetError(MS_MISCERR,"msComputeKernelDensityDataset()","failed to create in-memory gdal dataset for interpolated data"); status = MS_FAILURE; free(iValues); + return status; } adfGeoTransform[0] = map->extent.minx - map->cellsize * 0.5; /* top left x */ adfGeoTransform[1] = map->cellsize;/* w-e pixel resolution */ diff --git a/mapcairo.c b/mapcairo.c index 9da189b878..1595abc304 100644 --- a/mapcairo.c +++ b/mapcairo.c @@ -174,7 +174,7 @@ static cairoFaceCache* getCairoFontFace(cairoCacheData *cache, FT_Face ftface) { cur->options = cairo_font_options_create(); cairo_font_options_set_hint_style(cur->options,CAIRO_HINT_STYLE_NONE); return cur; -} +} #define msCairoSetSourceColor(cr, c) cairo_set_source_rgba((cr),(c)->red/255.0,(c)->green/255.0,(c)->blue/255.0,(c)->alpha/255.0); @@ -907,6 +907,7 @@ void freeSVGCache(symbolObj *s) { free(cache->pixmap_buffer); } msFree(s->renderer_cache); + s->renderer_cache = NULL; #endif } @@ -1043,8 +1044,7 @@ int msRenderRasterizedSVGSymbol(imageObj *img, double x, double y, symbolObj *sy height = surface_h = symbol->sizey; } if (style->rotation != 0) { - surface_w = MS_NINT(width * 1.415); - surface_h = MS_NINT(height * 1.415); + surface_w = surface_h = MS_NINT(MS_MAX(height, width) * 1.415); } surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, surface_w, surface_h); diff --git a/mapcluster.c b/mapcluster.c index 9abb4bd607..daf972afbb 100644 --- a/mapcluster.c +++ b/mapcluster.c @@ -1440,7 +1440,12 @@ int msClusterLayerOpen(layerObj *layer) return MS_FAILURE; if (layer->layerinfo) - return MS_SUCCESS; /* already open */ + { + if (layer->vtable->LayerOpen != msClusterLayerOpen) + msLayerClose(layer); + else + return MS_SUCCESS; /* already open */ + } layerinfo = msClusterInitialize(layer); @@ -1497,6 +1502,55 @@ int msClusterLayerOpen(layerObj *layer) return MS_SUCCESS; } +int msClusterLayerTranslateFilter(layerObj *layer, expressionObj *filter, char *filteritem) +{ + msClusterLayerInfo* layerinfo = layer->layerinfo; + + if (!layerinfo) { + msSetError(MS_MISCERR, "Layer is not open: %s", "msClusterLayerTranslateFilter()", layer->name); + return MS_FAILURE; + } + + if (layerinfo->srcLayer.filter.type == MS_EXPRESSION && layerinfo->srcLayer.filter.tokens == NULL) + msTokenizeExpression(&(layerinfo->srcLayer.filter), layer->items, &(layer->numitems)); + + return layerinfo->srcLayer.vtable->LayerTranslateFilter(&layerinfo->srcLayer, &layerinfo->srcLayer.filter, filteritem); +} + +char* msClusterLayerEscapeSQLParam(layerObj *layer, const char* pszString) +{ + msClusterLayerInfo* layerinfo = layer->layerinfo; + + if (!layerinfo) { + msSetError(MS_MISCERR, "Layer is not open: %s", "msClusterLayerEscapeSQLParam()", layer->name); + return msStrdup(""); + } + + return layerinfo->srcLayer.vtable->LayerEscapeSQLParam(&layerinfo->srcLayer, pszString); +} + +int msClusterLayerGetAutoProjection(layerObj *layer, projectionObj* projection) +{ + msClusterLayerInfo* layerinfo = layer->layerinfo; + + if (!layerinfo) { + msSetError(MS_MISCERR, "Layer is not open: %s", "msClusterLayerGetAutoProjection()", layer->name); + return MS_FAILURE; + } + + return layerinfo->srcLayer.vtable->LayerGetAutoProjection(&layerinfo->srcLayer, projection); +} + +int msClusterLayerGetPaging(layerObj *layer) +{ + return MS_FALSE; +} + +void msClusterLayerEnablePaging(layerObj *layer, int value) +{ + return; +} + void msClusterLayerCopyVirtualTable(layerVTableObj* vtable) { vtable->LayerInitItemInfo = msClusterLayerInitItemInfo; @@ -1514,6 +1568,14 @@ void msClusterLayerCopyVirtualTable(layerVTableObj* vtable) vtable->LayerGetNumFeatures = msClusterLayerGetNumFeatures; vtable->LayerGetAutoStyle = msClusterLayerGetAutoStyle; + vtable->LayerTranslateFilter = msClusterLayerTranslateFilter; + /* vtable->LayerSupportsCommonFilters, use driver implementation */ + vtable->LayerEscapeSQLParam = msClusterLayerEscapeSQLParam; + /* vtable->LayerEscapePropertyName, use driver implementation */ + + vtable->LayerEnablePaging = msClusterLayerEnablePaging; + vtable->LayerGetPaging = msClusterLayerGetPaging; + vtable->LayerGetAutoProjection = msClusterLayerGetAutoProjection; } #ifdef USE_CLUSTER_PLUGIN @@ -1531,8 +1593,7 @@ PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj *layer) #endif -int -msClusterLayerInitializeVirtualTable(layerObj *layer) +int msClusterLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); diff --git a/mapcopy.c b/mapcopy.c index 30d893dfdf..406d91ab44 100644 --- a/mapcopy.c +++ b/mapcopy.c @@ -500,6 +500,7 @@ int msCopyStyle(styleObj *dst, styleObj *src) MS_COPYSTELEM(offsetx); MS_COPYSTELEM(offsety); MS_COPYSTELEM(angle); + MS_COPYSTELEM(autoangle); MS_COPYSTELEM(minvalue); MS_COPYSTELEM(maxvalue); MS_COPYSTELEM(opacity); @@ -925,6 +926,19 @@ int msCopyScaleToken(scaleTokenObj *src, scaleTokenObj *dst) { return MS_SUCCESS; } +int msCopyCompositingFilter(CompositingFilter **pdst, CompositingFilter *src) { + CompositingFilter *dst = NULL; + if(!src) { + *pdst = NULL; + return MS_SUCCESS; + } + if(!dst) { + dst = *pdst = msSmallMalloc(sizeof(CompositingFilter)); + } + dst->filter = msStrdup(src->filter); + return MS_SUCCESS; +} + int msCopyCompositer(LayerCompositer **ldst, LayerCompositer *src) { LayerCompositer *dst = NULL; if(!src) { @@ -942,7 +956,7 @@ int msCopyCompositer(LayerCompositer **ldst, LayerCompositer *src) { dst->comp_op = src->comp_op; dst->opacity = src->opacity; dst->next = NULL; - /* TODO dst->filter */ + msCopyCompositingFilter(&dst->filter, src->filter); src = src->next; } return MS_SUCCESS; diff --git a/mapdraw.c b/mapdraw.c index 696db350cb..013d2ee448 100644 --- a/mapdraw.c +++ b/mapdraw.c @@ -55,6 +55,7 @@ imageObj *msPrepareImage(mapObj *map, int allow_nonsquare) return(NULL); } + msFreeLabelCache(&(map->labelcache)); msInitLabelCache(&(map->labelcache)); /* this clears any previously allocated cache */ /* clear any previously created mask layer images */ @@ -219,7 +220,8 @@ imageObj *msDrawMap(mapObj *map, int querymap) #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) enum MS_CONNECTION_TYPE lastconnectiontype; httpRequestObj *pasOWSReqInfo=NULL; - int numOWSLayers=0, numOWSRequests=0; + int numOWSLayers=0; + int numOWSRequests=0; wmsParamsObj sLastWMSParams; #endif @@ -255,30 +257,43 @@ imageObj *msDrawMap(mapObj *map, int querymap) */ numOWSLayers=0; for(i=0; inumlayers; i++) { - if(map->layerorder[i] != -1 && - msLayerIsVisible(map, GET_LAYER(map,map->layerorder[i]))) + if(map->layerorder[i] == -1 ) + continue; + + lp = GET_LAYER(map,map->layerorder[i]); + if( lp->connectiontype != MS_WMS && + lp->connectiontype != MS_WFS ) { + continue; + } numOWSLayers++; } - if (numOWSLayers > 0) { + /* Alloc and init pasOWSReqInfo... */ - pasOWSReqInfo = (httpRequestObj *)malloc((numOWSLayers+1)*sizeof(httpRequestObj)); + pasOWSReqInfo = (httpRequestObj *)malloc(numOWSLayers*sizeof(httpRequestObj)); if (pasOWSReqInfo == NULL) { msSetError(MS_MEMERR, "Allocation of httpRequestObj failed.", "msDrawMap()"); return NULL; } - msHTTPInitRequestObj(pasOWSReqInfo, numOWSLayers+1); + msHTTPInitRequestObj(pasOWSReqInfo, numOWSLayers); msInitWmsParamsObj(&sLastWMSParams); /* Pre-download all WMS/WFS layers in parallel before starting to draw map */ lastconnectiontype = MS_SHAPEFILE; - for(i=0; numOWSLayers && inumlayers; i++) { - if(map->layerorder[i] == -1 || !msLayerIsVisible(map, GET_LAYER(map,map->layerorder[i]))) + for(i=0; inumlayers; i++) { + if(map->layerorder[i] == -1 ) continue; lp = GET_LAYER(map,map->layerorder[i]); + if( lp->connectiontype != MS_WMS && + lp->connectiontype != MS_WFS ) { + continue; + } + + if( !msLayerIsVisible(map, lp) ) + continue; #ifdef USE_WMS_LYR if(lp->connectiontype == MS_WMS) { @@ -305,9 +320,7 @@ imageObj *msDrawMap(mapObj *map, int querymap) lastconnectiontype = lp->connectiontype; } -#ifdef USE_WMS_LYR msFreeWmsParamsObj(&sLastWMSParams); -#endif } /* if numOWSLayers > 0 */ if(numOWSRequests && msOWSExecuteRequests(pasOWSReqInfo, numOWSRequests, map, MS_TRUE) == MS_FAILURE) { @@ -581,17 +594,8 @@ int msLayerIsVisible(mapObj *map, layerObj *layer) if(layer->type == MS_LAYER_QUERY || layer->type == MS_LAYER_TILEINDEX) return(MS_FALSE); if((layer->status != MS_ON) && (layer->status != MS_DEFAULT)) return(MS_FALSE); - /* Only return MS_FALSE if it is definitely false. Sometimes it will return MS_UNKNOWN, which we - ** consider true, for this use case (it might be visible, try and draw it, see what happens). */ - if ( msExtentsOverlap(map, layer) == MS_FALSE ) { - if( layer->debug >= MS_DEBUGLEVEL_V ) { - msDebug("msLayerIsVisible(): Skipping layer (%s) because LAYER.EXTENT does not intersect MAP.EXTENT\n", layer->name); - } - return(MS_FALSE); - } - - if(msEvalContext(map, layer, layer->requires) == MS_FALSE) return(MS_FALSE); - + /* Do comparisons of layer scale vs map scale now, since msExtentsOverlap() */ + /* can be slow */ if(map->scaledenom > 0) { /* layer scale boundaries should be checked first */ @@ -601,13 +605,27 @@ int msLayerIsVisible(mapObj *map, layerObj *layer) } return(MS_FALSE); } - if((layer->minscaledenom > 0) && (map->scaledenom <= layer->minscaledenom)) { + if(/*(layer->minscaledenom > 0) &&*/ (map->scaledenom <= layer->minscaledenom)) { if( layer->debug >= MS_DEBUGLEVEL_V ) { msDebug("msLayerIsVisible(): Skipping layer (%s) because LAYER.MINSCALE is too large for this MAP scale\n", layer->name); } return(MS_FALSE); } - + } + + /* Only return MS_FALSE if it is definitely false. Sometimes it will return MS_UNKNOWN, which we + ** consider true, for this use case (it might be visible, try and draw it, see what happens). */ + if ( msExtentsOverlap(map, layer) == MS_FALSE ) { + if( layer->debug >= MS_DEBUGLEVEL_V ) { + msDebug("msLayerIsVisible(): Skipping layer (%s) because LAYER.EXTENT does not intersect MAP.EXTENT\n", layer->name); + } + return(MS_FALSE); + } + + if(msEvalContext(map, layer, layer->requires) == MS_FALSE) return(MS_FALSE); + + if(map->scaledenom > 0) { + /* now check class scale boundaries (all layers *must* pass these tests) */ if(layer->numclasses > 0) { for(i=0; inumclasses; i++) { @@ -771,6 +789,7 @@ int msDrawLayer(mapObj *map, layerObj *layer, imageObj *image) "msDrawLayer()"); return (MS_FAILURE); } + image_draw->map = map; renderer->startLayer(image_draw,map,layer); } } @@ -937,8 +956,110 @@ int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image) if(layer->transform == MS_TRUE) { searchrect = map->extent; #ifdef USE_PROJ - if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) - msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ + if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) { + int bDone = MS_FALSE; + +#ifdef USE_GDAL + if( layer->connectiontype == MS_UVRASTER ) + { + /* Nasty hack to make msUVRASTERLayerWhichShapes() aware that the */ + /* original area of interest is (map->extent, map->projection)... */ + /* Useful when dealin with UVRASTER that extend beyond 180 deg */ + msUVRASTERLayerUseMapExtentAndProjectionForNextWhichShapes( layer, map ); + } +#endif + + /* For UVRaster, it is important that the searchrect is not too large */ + /* to avoid insufficient intermediate raster resolution, which could */ + /* happen if we use the default code path, given potential reprojection */ + /* issues when using a map extent that is not in the validity area of */ + /* the layer projection. */ + if( layer->connectiontype == MS_UVRASTER && + !layer->projection.gt.need_geotransform && + !(pj_is_latlong(map->projection.proj) && + pj_is_latlong(layer->projection.proj)) ) { + rectObj layer_ori_extent; + + if( msLayerGetExtent(layer, &layer_ori_extent) == MS_SUCCESS ) { + projectionObj map_proj; + + double map_extent_minx = map->extent.minx; + double map_extent_miny = map->extent.miny; + double map_extent_maxx = map->extent.maxx; + double map_extent_maxy = map->extent.maxy; + rectObj layer_extent = layer_ori_extent; + + /* Create a variant of map->projection without geotransform for */ + /* conveniency */ + msInitProjection(&map_proj); + msCopyProjection(&map_proj, &map->projection); + map_proj.gt.need_geotransform = MS_FALSE; + if( map->projection.gt.need_geotransform ) { + map_extent_minx = map->projection.gt.geotransform[0] + + map->projection.gt.geotransform[1] * map->extent.minx + + map->projection.gt.geotransform[2] * map->extent.miny; + map_extent_miny = map->projection.gt.geotransform[3] + + map->projection.gt.geotransform[4] * map->extent.minx + + map->projection.gt.geotransform[5] * map->extent.miny; + map_extent_maxx = map->projection.gt.geotransform[0] + + map->projection.gt.geotransform[1] * map->extent.maxx + + map->projection.gt.geotransform[2] * map->extent.maxy; + map_extent_maxy = map->projection.gt.geotransform[3] + + map->projection.gt.geotransform[4] * map->extent.maxx + + map->projection.gt.geotransform[5] * map->extent.maxy; + } + + /* Reproject layer extent to map projection */ + msProjectRect(&layer->projection, &map_proj, &layer_extent); + + if( layer_extent.minx <= map_extent_minx && + layer_extent.miny <= map_extent_miny && + layer_extent.maxx >= map_extent_maxx && + layer_extent.maxy >= map_extent_maxy ) { + /* do nothing special if area to map is inside layer extent */ + } + else { + if( layer_extent.minx >= map_extent_minx && + layer_extent.maxx <= map_extent_maxx && + layer_extent.miny >= map_extent_miny && + layer_extent.maxy <= map_extent_maxy ) { + /* if the area to map is larger than the layer extent, then */ + /* use full layer extent and add some margin to reflect the */ + /* proportion of the useful area over the requested bbox */ + double extra_x = + (map_extent_maxx - map_extent_minx) / + (layer_extent.maxx - layer_extent.minx) * + (layer_ori_extent.maxx - layer_ori_extent.minx); + double extra_y = + (map_extent_maxy - map_extent_miny) / + (layer_extent.maxy - layer_extent.miny) * + (layer_ori_extent.maxy - layer_ori_extent.miny); + searchrect.minx = layer_ori_extent.minx - extra_x / 2; + searchrect.maxx = layer_ori_extent.maxx + extra_x / 2; + searchrect.miny = layer_ori_extent.miny - extra_y / 2; + searchrect.maxy = layer_ori_extent.maxy + extra_y / 2; + } + else + { + /* otherwise clip the map extent with the reprojected layer */ + /* extent */ + searchrect.minx = MS_MAX( map_extent_minx, layer_extent.minx ); + searchrect.maxx = MS_MIN( map_extent_maxx, layer_extent.maxx ); + searchrect.miny = MS_MAX( map_extent_miny, layer_extent.miny ); + searchrect.maxy = MS_MIN( map_extent_maxy, layer_extent.maxy ); + /* and reproject into the layer projection */ + msProjectRect(&map_proj, &layer->projection, &searchrect); + } + bDone = MS_TRUE; + } + + msFreeProjection(&map_proj); + } + } + + if( !bDone ) + msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ + } #endif } else { searchrect.minx = searchrect.miny = 0; @@ -947,6 +1068,14 @@ int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image) } status = msLayerWhichShapes(layer, searchrect, MS_FALSE); + +#ifdef USE_GDAL + if( layer->connectiontype == MS_UVRASTER ) + { + msUVRASTERLayerUseMapExtentAndProjectionForNextWhichShapes( layer, NULL ); + } +#endif + if(status == MS_DONE) { /* no overlap */ msLayerClose(layer); return MS_SUCCESS; @@ -1239,7 +1368,7 @@ int msDrawQueryLayer(mapObj *map, layerObj *layer, imageObj *image) colorbuffer[i] = layer->class[i]->styles[0]->outlinecolor; /* if no color, save the outlinecolor from the BOTTOM style */ layer->class[i]->styles[0]->outlinecolor = map->querymap.color; } - } else { + } else if (layer->class[i]->numstyles > 0) { if(MS_VALID_COLOR(layer->class[i]->styles[layer->class[i]->numstyles-1]->color)) { colorbuffer[i] = layer->class[i]->styles[layer->class[i]->numstyles-1]->color; /* save the color from the TOP style */ layer->class[i]->styles[layer->class[i]->numstyles-1]->color = map->querymap.color; @@ -1247,6 +1376,9 @@ int msDrawQueryLayer(mapObj *map, layerObj *layer, imageObj *image) colorbuffer[i] = layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor; /* if no color, save the outlinecolor from the TOP style */ layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor = map->querymap.color; } + } else if (layer->class[i]->numlabels > 0) { + colorbuffer[i] = layer->class[i]->labels[0]->color; + layer->class[i]->labels[0]->color = map->querymap.color; } mindistancebuffer[i] = -1; /* RFC77 TODO: only using the first label, is that cool? */ @@ -1355,12 +1487,16 @@ int msDrawQueryLayer(mapObj *map, layerObj *layer, imageObj *image) layer->class[i]->styles[0]->color = colorbuffer[i]; else if(MS_VALID_COLOR(layer->class[i]->styles[0]->outlinecolor)) layer->class[i]->styles[0]->outlinecolor = colorbuffer[i]; /* if no color, restore outlinecolor for the BOTTOM style */ - } else { + } else if (layer->class[i]->numstyles > 0) { if(MS_VALID_COLOR(layer->class[i]->styles[layer->class[i]->numstyles-1]->color)) layer->class[i]->styles[layer->class[i]->numstyles-1]->color = colorbuffer[i]; else if(MS_VALID_COLOR(layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor)) layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor = colorbuffer[i]; /* if no color, restore outlinecolor for the TOP style */ } + else if (layer->class[i]->numlabels > 0) { + if(MS_VALID_COLOR(layer->class[i]->labels[0]->color)) + layer->class[i]->labels[0]->color = colorbuffer[i]; + } if(layer->class[i]->numlabels > 0) layer->class[i]->labels[0]->mindistance = mindistancebuffer[i]; /* RFC77 TODO: again, only using the first label, is that cool? */ @@ -1568,7 +1704,7 @@ int pointLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer, shapeObj } if(MS_DRAW_LABELS(drawmode)) { if (layer->labelcache) { - if (msAddLabelGroup(map, image, layer->index, c, shape, point, -1) != MS_SUCCESS) return (MS_FAILURE); + if (msAddLabelGroup(map, image, layer, c, shape, point, -1) != MS_SUCCESS) return (MS_FAILURE); } else { for (l = 0; l < layer->class[c]->numlabels; l++) if(msGetLabelStatus(map,layer,shape,layer->class[c]->labels[l]) == MS_ON) { @@ -1765,7 +1901,7 @@ int polygonLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer, for (i = 0; i < layer->class[c]->numlabels; i++) if (layer->class[c]->labels[i]->angle != 0) layer->class[c]->labels[i]->angle -= map->gt.rotation_angle; /* TODO: is this correct ??? */ if (layer->labelcache) { - if (msAddLabelGroup(map, image, layer->index, c, anno_shape, &annopnt, + if (msAddLabelGroup(map, image, layer, c, anno_shape, &annopnt, MS_MIN(shape->bounds.maxx - shape->bounds.minx, shape->bounds.maxy - shape->bounds.miny)) != MS_SUCCESS) { return MS_FAILURE; } @@ -2261,7 +2397,7 @@ void offsetAndTest(mapObj *map, labelCacheMemberObj *cachePtr, double ox, double } } for(j=0; jlabel->numstyles; j++) { - if(ts->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) { + if(ts->label->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) { scratch->poly = scratch_line; offset_label_bounds(ts->style_bounds[j], scratch, ox, oy); status = msTestLabelCacheCollisions(map, cachePtr, scratch, priority, label_idx); @@ -2305,8 +2441,8 @@ void offsetAndTest(mapObj *map, labelCacheMemberObj *cachePtr, double ox, double } if(ts->style_bounds) { for(j=0; jlabel->numstyles; j++) { - if(ts->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT || - ts->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) { + if(ts->label->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT || + ts->label->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) { offset_label_bounds(ts->style_bounds[j], ts->style_bounds[j], ox, oy); } } @@ -2378,8 +2514,8 @@ int msDrawOffsettedLabels(imageObj *image, mapObj *map, int priority) #define otest(ox,oy) if((x0+(ox)) >= labelcache->gutter &&\ (y0+(oy)) >= labelcache->gutter &&\ - (x0+(ox)) < image->width + labelcache->gutter &&\ - (y0+(oy)) < image->height + labelcache->gutter) {\ + (x0+(ox)) < image->width - labelcache->gutter &&\ + (y0+(oy)) < image->height - labelcache->gutter) {\ scratch_line.point = scratch_points;\ scratch.poly = &scratch_line; \ offsetAndTest(map,cachePtr,(ox),(oy),priority,l,&scratch); \ @@ -2503,7 +2639,7 @@ int msDrawOffsettedLabels(imageObj *image, mapObj *map, int priority) /* here's where we draw the label styles */ for(i=0; ilabel->numstyles; i++) { if(ts->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) { - retval = msDrawMarkerSymbol(map, image, &(cachePtr->point), ts->label->styles[i], layerPtr->scalefactor); + retval = msDrawMarkerSymbol(map, image, &(labelLeader.line->point[1]), ts->label->styles[i], layerPtr->scalefactor); if(UNLIKELY(retval == MS_FAILURE)) { goto offset_cleanup; } @@ -2944,7 +3080,7 @@ int msDrawLabelCache(mapObj *map, imageObj *image) textSymbolPtr->rotation, textSymbolPtr->label->buffer * textSymbolPtr->scalefactor, &metrics_bounds); if(need_labelpoly) get_metrics(&(cachePtr->point), MS_CC, textSymbolPtr->textpath, - marker_offset_x + label_offset_x, marker_offset_y + label_offset_y, + label_offset_x, label_offset_y, textSymbolPtr->rotation, 1, &labelpoly_bounds); } } else { /* explicit position */ @@ -2952,7 +3088,7 @@ int msDrawLabelCache(mapObj *map, imageObj *image) metrics_bounds.poly = &metrics_line; textSymbolPtr->annopoint = get_metrics(&(cachePtr->point), MS_CC, textSymbolPtr->textpath, label_offset_x, label_offset_y, textSymbolPtr->rotation, textSymbolPtr->label->buffer * textSymbolPtr->scalefactor, &metrics_bounds); - if(need_labelpoly) get_metrics(&(cachePtr->point), textSymbolPtr->label->position, textSymbolPtr->textpath, + if(need_labelpoly) get_metrics(&(cachePtr->point), MS_CC, textSymbolPtr->textpath, label_offset_x, label_offset_y, textSymbolPtr->rotation, 1, &labelpoly_bounds); } else { metrics_bounds.poly = &metrics_line; diff --git a/mapdrawgdal.c b/mapdrawgdal.c index f90f2acbd6..72836c9238 100644 --- a/mapdrawgdal.c +++ b/mapdrawgdal.c @@ -32,7 +32,7 @@ #include "mapserver.h" #include "mapresample.h" #include "mapthread.h" - +#include "maptime.h" extern int InvGeoTransform( double *gt_in, double *gt_out ); @@ -1270,6 +1270,9 @@ LoadGDALImages( GDALDatasetH hDS, int band_numbers[4], int band_count, if( bGotNoData && pafRawData[i] == fNoDataValue ) continue; + if( CPLIsNan(pafRawData[i]) ) + continue; + if( !bMinMaxSet ) { dfScaleMin = dfScaleMax = pafRawData[i]; bMinMaxSet = TRUE; @@ -1714,6 +1717,9 @@ msDrawRasterLayerGDAL_16BitClassification( unsigned char *rb_cmap[4]; CPLErr eErr; rasterBufferObj *mask_rb = NULL; + int lastC; + struct mstimeval starttime, endtime; + if(layer->mask) { int ret; layerObj *maskLayer = GET_LAYER(map, msGetLayerIndex(map,layer->mask)); @@ -1764,6 +1770,9 @@ msDrawRasterLayerGDAL_16BitClassification( if( bGotNoData && pafRawData[i] == fNoDataValue ) continue; + if( CPLIsNan(pafRawData[i]) ) + continue; + if( !bGotFirstValue ) { fDataMin = fDataMax = pafRawData[i]; bGotFirstValue = TRUE; @@ -1869,6 +1878,12 @@ msDrawRasterLayerGDAL_16BitClassification( rb_cmap[2] = (unsigned char *) msSmallCalloc(1,nBucketCount); rb_cmap[3] = (unsigned char *) msSmallCalloc(1,nBucketCount); + + if(layer->debug >= MS_DEBUGLEVEL_TUNING) { + msGettimeofday(&starttime, NULL); + } + + lastC = -1; for(i=0; i < nBucketCount; i++) { double dfOriginalValue; @@ -1876,7 +1891,11 @@ msDrawRasterLayerGDAL_16BitClassification( dfOriginalValue = (i+0.5) / dfScaleRatio + dfScaleMin; - c = msGetClass_FloatRGB(layer, (float) dfOriginalValue, -1, -1, -1); + /* The creation of buckets takes a significant time when they are many, and many classes + as well. When iterating over buckets, a faster strategy is to reuse first the last used + class index. */ + c = msGetClass_FloatRGB_WithFirstClassToTry(layer, (float) dfOriginalValue, -1, -1, -1, lastC); + lastC = c; if( c != -1 ) { int s; @@ -1898,6 +1917,13 @@ msDrawRasterLayerGDAL_16BitClassification( } } + if(layer->debug >= MS_DEBUGLEVEL_TUNING) { + msGettimeofday(&endtime, NULL); + msDebug("msDrawRasterGDAL_16BitClassification() bucket creation time: %.3fs\n", + (endtime.tv_sec+endtime.tv_usec/1.0e6)- + (starttime.tv_sec+starttime.tv_usec/1.0e6) ); + } + /* ==================================================================== */ /* Now process the data, applying to the working imageObj. */ /* ==================================================================== */ @@ -1915,6 +1941,9 @@ msDrawRasterLayerGDAL_16BitClassification( continue; } + if( CPLIsNan(fRawValue) ) + continue; + if(SKIP_MASK(j,i)) continue; diff --git a/mapfile.c b/mapfile.c index 244c0d60a6..c3aed812e5 100644 --- a/mapfile.c +++ b/mapfile.c @@ -104,6 +104,16 @@ int msValidateParameter(char *value, char *pattern1, char *pattern2, char *patte return(MS_FAILURE); } +int msIsValidRegex(const char* e) { + ms_regex_t re; + if(ms_regcomp(&re, e, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { + msSetError(MS_REGEXERR, "Failed to compile expression (%s).", "msEvalRegex()", e); + return(MS_FALSE); + } + ms_regfree(&re); + return MS_TRUE; +} + int msEvalRegex(const char *e, const char *s) { ms_regex_t re; @@ -124,6 +134,26 @@ int msEvalRegex(const char *e, const char *s) return(MS_TRUE); } +int msCaseEvalRegex(const char *e, const char *s) +{ + ms_regex_t re; + + if(!e || !s) return(MS_FALSE); + + if(ms_regcomp(&re, e, MS_REG_EXTENDED|MS_REG_ICASE|MS_REG_NOSUB) != 0) { + msSetError(MS_REGEXERR, "Failed to compile expression (%s).", "msEvalRegex()", e); + return(MS_FALSE); + } + + if(ms_regexec(&re, s, 0, NULL, 0) != 0) { /* no match */ + ms_regfree(&re); + return(MS_FALSE); + } + ms_regfree(&re); + + return(MS_TRUE); +} + #ifdef USE_MSFREE void msFree(void *p) { @@ -3709,6 +3739,22 @@ int initLayerCompositer(LayerCompositer *compositer) { compositer->filter = NULL; return MS_SUCCESS; } + +int freeLayerCompositers(LayerCompositer * item) { + while(item) { + LayerCompositer * next = item->next; + + if (item->filter) { + msFree(item->filter->filter); + msFree(item->filter); + } + msFree(item); + + item=next; + } + return MS_SUCCESS; +} + /* ** Initialize, load and free a single layer structure */ @@ -3978,6 +4024,8 @@ int freeLayer(layerObj *layer) msFree(layer->sortBy.properties[i].item); msFree(layer->sortBy.properties); + freeLayerCompositers(layer->compositer); + return MS_SUCCESS; } @@ -4108,7 +4156,11 @@ int loadLayerCompositer(LayerCompositer *compositer) { case COMPFILTER: compositer->filter = msSmallMalloc(sizeof(CompositingFilter)); initCompositingFilter(compositer->filter); - if(getString(&compositer->filter->filter) == MS_FAILURE) return(MS_FAILURE); + if(getString(&compositer->filter->filter) == MS_FAILURE) { + msFree(compositer->filter); + compositer->filter=NULL; + return(MS_FAILURE); + } break; case COMPOP: { char *compop=NULL; @@ -4172,6 +4224,11 @@ int loadLayerCompositer(LayerCompositer *compositer) { else { msSetError(MS_PARSEERR,"Unknown COMPOP \"%s\"", "loadLayerCompositer()", compop); free(compop); + if (compositer->filter) { + msFree(compositer->filter->filter); + msFree(compositer->filter); + compositer->filter=NULL; + } return MS_FAILURE; } free(compop); @@ -4180,14 +4237,30 @@ int loadLayerCompositer(LayerCompositer *compositer) { case END: return MS_SUCCESS; case OPACITY: - if (getInteger(&(compositer->opacity)) == -1) + if (getInteger(&(compositer->opacity)) == -1) { + if (compositer->filter) { + msFree(compositer->filter->filter); + msFree(compositer->filter); + compositer->filter=NULL; + } return MS_FAILURE; + } if(compositer->opacity<0 || compositer->opacity>100) { + if (compositer->filter) { + msFree(compositer->filter->filter); + msFree(compositer->filter); + compositer->filter=NULL; + } msSetError(MS_PARSEERR,"OPACITY must be between 0 and 100 (line %d)","loadLayerCompositer()",msyylineno); return MS_FAILURE; } break; default: + if (compositer->filter) { + msFree(compositer->filter->filter); + msFree(compositer->filter); + compositer->filter=NULL; + } msSetError(MS_IDENTERR, "Parsing error 2 near (%s):(line %d)", "loadLayerCompositer()", msyystring_buffer, msyylineno ); return(MS_FAILURE); } @@ -4240,7 +4313,10 @@ int loadLayer(layerObj *layer, mapObj *map) case(COMPOSITE): { LayerCompositer *compositer = msSmallMalloc(sizeof(LayerCompositer)); initLayerCompositer(compositer); - if(MS_FAILURE == loadLayerCompositer(compositer)) return -1; + if(MS_FAILURE == loadLayerCompositer(compositer)) { + msFree(compositer); + return -1; + } if(!layer->compositer) { layer->compositer = compositer; } else { @@ -4695,6 +4771,110 @@ int msUpdateLayerFromString(layerObj *layer, char *string, int url_string) return MS_SUCCESS; } +static void writeCompositingFilter(FILE *stream, int indent, CompositingFilter *filter) { + if(filter) { + writeString(stream, indent, "COMPFILTER", "", filter->filter); + } +} + +static void writeLayerCompositer(FILE *stream, int indent, LayerCompositer *compositor) { + indent++; + while(compositor) { + writeBlockBegin(stream, indent, "COMPOSITE"); + writeCompositingFilter(stream, indent, compositor->filter); + if(compositor->comp_op != MS_COMPOP_SRC_OVER) { + switch(compositor->comp_op) { + case MS_COMPOP_CLEAR: + writeString(stream, indent, "COMPOP", NULL, "clear"); + break; + case MS_COMPOP_COLOR_BURN: + writeString(stream, indent, "COMPOP", NULL, "color-burn"); + break; + case MS_COMPOP_COLOR_DODGE: + writeString(stream, indent, "COMPOP", NULL, "color-dodge"); + break; + case MS_COMPOP_CONTRAST: + writeString(stream, indent, "COMPOP", NULL, "contrast"); + break; + case MS_COMPOP_DARKEN: + writeString(stream, indent, "COMPOP", NULL, "darken"); + break; + case MS_COMPOP_DIFFERENCE: + writeString(stream, indent, "COMPOP", NULL, "difference"); + break; + case MS_COMPOP_DST: + writeString(stream, indent, "COMPOP", NULL, "dst"); + break; + case MS_COMPOP_DST_ATOP: + writeString(stream, indent, "COMPOP", NULL, "dst-atop"); + break; + case MS_COMPOP_DST_IN: + writeString(stream, indent, "COMPOP", NULL, "dst-in"); + break; + case MS_COMPOP_DST_OUT: + writeString(stream, indent, "COMPOP", NULL, "dst-out"); + break; + case MS_COMPOP_DST_OVER: + writeString(stream, indent, "COMPOP", NULL, "dst-over"); + break; + case MS_COMPOP_EXCLUSION: + writeString(stream, indent, "COMPOP", NULL, "exclusion"); + break; + case MS_COMPOP_HARD_LIGHT: + writeString(stream, indent, "COMPOP", NULL, "hard-light"); + break; + case MS_COMPOP_INVERT: + writeString(stream, indent, "COMPOP", NULL, "invert"); + break; + case MS_COMPOP_INVERT_RGB: + writeString(stream, indent, "COMPOP", NULL, "invert-rgb"); + break; + case MS_COMPOP_LIGHTEN: + writeString(stream, indent, "COMPOP", NULL, "lighten"); + break; + case MS_COMPOP_MINUS: + writeString(stream, indent, "COMPOP", NULL, "minus"); + break; + case MS_COMPOP_MULTIPLY: + writeString(stream, indent, "COMPOP", NULL, "multiply"); + break; + case MS_COMPOP_OVERLAY: + writeString(stream, indent, "COMPOP", NULL, "overlay"); + break; + case MS_COMPOP_PLUS: + writeString(stream, indent, "COMPOP", NULL, "plus"); + break; + case MS_COMPOP_SCREEN: + writeString(stream, indent, "COMPOP", NULL, "screen"); + break; + case MS_COMPOP_SOFT_LIGHT: + writeString(stream, indent, "COMPOP", NULL, "soft-light"); + break; + case MS_COMPOP_SRC: + writeString(stream, indent, "COMPOP", NULL, "src"); + break; + case MS_COMPOP_SRC_ATOP: + writeString(stream, indent, "COMPOP", NULL, "src-atop"); + break; + case MS_COMPOP_SRC_IN: + writeString(stream, indent, "COMPOP", NULL, "src-in"); + break; + case MS_COMPOP_SRC_OUT: + writeString(stream, indent, "COMPOP", NULL, "src-out"); + break; + case MS_COMPOP_SRC_OVER: + writeString(stream, indent, "COMPOP", NULL, "src-over"); + break; + case MS_COMPOP_XOR: + writeString(stream, indent, "COMPOP", NULL, "xor"); + break; + } + } + writeNumber(stream,indent,"OPACITY",100,compositor->opacity); + writeBlockEnd(stream,indent,"COMPOSITE"); + compositor = compositor->next; + } +} static void writeLayer(FILE *stream, int indent, layerObj *layer) { int i; @@ -4710,6 +4890,7 @@ static void writeLayer(FILE *stream, int indent, layerObj *layer) writeString(stream, indent, "CLASSGROUP", NULL, layer->classgroup); writeString(stream, indent, "CLASSITEM", NULL, layer->classitem); writeCluster(stream, indent, &(layer->cluster)); + writeLayerCompositer(stream, indent, layer->compositer); writeString(stream, indent, "CONNECTION", NULL, layer->connection); writeKeyword(stream, indent, "CONNECTIONTYPE", layer->connectiontype, 10, MS_OGR, "OGR", MS_POSTGIS, "POSTGIS", MS_WMS, "WMS", MS_ORACLESPATIAL, "ORACLESPATIAL", MS_WFS, "WFS", MS_PLUGIN, "PLUGIN", MS_UNION, "UNION", MS_UVRASTER, "UVRASTER", MS_CONTOUR, "CONTOUR", MS_KERNELDENSITY, "KERNELDENSITY"); writeString(stream, indent, "DATA", NULL, layer->data); @@ -4760,7 +4941,7 @@ static void writeLayer(FILE *stream, int indent, layerObj *layer) writeNumber(stream, indent, "TOLERANCE", -1, layer->tolerance); writeKeyword(stream, indent, "TOLERANCEUNITS", layer->toleranceunits, 7, MS_INCHES, "INCHES", MS_FEET ,"FEET", MS_MILES, "MILES", MS_METERS, "METERS", MS_KILOMETERS, "KILOMETERS", MS_NAUTICALMILES, "NAUTICALMILES", MS_DD, "DD"); writeKeyword(stream, indent, "TRANSFORM", layer->transform, 10, MS_FALSE, "FALSE", MS_UL, "UL", MS_UC, "UC", MS_UR, "UR", MS_CL, "CL", MS_CC, "CC", MS_CR, "CR", MS_LL, "LL", MS_LC, "LC", MS_LR, "LR"); - writeKeyword(stream, indent, "TYPE", layer->type, 8, MS_LAYER_POINT, "POINT", MS_LAYER_LINE, "LINE", MS_LAYER_POLYGON, "POLYGON", MS_LAYER_RASTER, "RASTER", MS_LAYER_QUERY, "QUERY", MS_LAYER_CIRCLE, "CIRCLE", MS_LAYER_TILEINDEX, "TILEINDEX", MS_LAYER_CHART, "CHART"); + writeKeyword(stream, indent, "TYPE", layer->type, 9, MS_LAYER_POINT, "POINT", MS_LAYER_LINE, "LINE", MS_LAYER_POLYGON, "POLYGON", MS_LAYER_RASTER, "RASTER", MS_LAYER_ANNOTATION, "ANNOTATION", MS_LAYER_QUERY, "QUERY", MS_LAYER_CIRCLE, "CIRCLE", MS_LAYER_TILEINDEX, "TILEINDEX", MS_LAYER_CHART, "CHART"); writeKeyword(stream, indent, "UNITS", layer->units, 9, MS_INCHES, "INCHES", MS_FEET ,"FEET", MS_MILES, "MILES", MS_METERS, "METERS", MS_KILOMETERS, "KILOMETERS", MS_NAUTICALMILES, "NAUTICALMILES", MS_DD, "DD", MS_PIXELS, "PIXELS", MS_PERCENTAGES, "PERCENTATGES"); writeHashTable(stream, indent, "VALIDATION", &(layer->validation)); @@ -6868,11 +7049,14 @@ int msUpdateMapFromURL(mapObj *map, char *variable, char *string) static void hashTableSubstituteString(hashTableObj *hash, const char *from, const char *to) { const char *key, *val; + char *new_val; key = msFirstKeyFromHashTable(hash); while(key != NULL) { val = msLookupHashTable(hash, key); if(strcasestr(val, from)) { - msInsertHashTable(hash, key, msCaseReplaceSubstring(msStrdup(val), from, to)); + new_val = msCaseReplaceSubstring(msStrdup(val), from, to); + msInsertHashTable(hash, key, new_val); + msFree(new_val); } key = msNextKeyFromHashTable(hash, key); } @@ -6986,6 +7170,24 @@ static void applyLayerDefaultSubstitutions(layerObj *layer, hashTableObj *table) return; } +static void applyHashTableDefaultSubstitutions(hashTableObj *hashTab, hashTableObj *table) +{ + const char *default_key = msFirstKeyFromHashTable(table); + while (default_key) { + if (!strncmp(default_key, "default_", 8)) { + size_t buffer_size = (strlen(default_key) - 5); + char *to = msLookupHashTable(table, default_key); + char *tag = (char *)msSmallMalloc(buffer_size); + snprintf(tag, buffer_size, "%%%s%%", &(default_key[8])); + + hashTableSubstituteString(hashTab, tag, to); + free(tag); + } + default_key = msNextKeyFromHashTable(table, default_key); + } + return; +} + /* ** Loop through layer metadata for keys that have a default_%key% pattern to replace ** remaining %key% entries by their default value. @@ -7011,6 +7213,7 @@ void msApplyDefaultSubstitutions(mapObj *map) applyLayerDefaultSubstitutions(layer, &(layer->validation)); /* ...then layer settings... */ applyLayerDefaultSubstitutions(layer, &(map->web.validation)); /* ...and finally web settings */ } + applyHashTableDefaultSubstitutions(&map->web.metadata, &(map->web.validation)); } char *_get_param_value(const char *key, char **names, char **values, int npairs) { diff --git a/mapgraticule.c b/mapgraticule.c index 688b45b3f9..246d31f41b 100644 --- a/mapgraticule.c +++ b/mapgraticule.c @@ -187,6 +187,19 @@ int msGraticuleLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) * These lines will be used when generating labels to get correct placement at arc/rect edge intersections. */ rectMapCoordinates = layer->map->extent; +#ifdef USE_PROJ + layer->project = msProjectionsDiffer(&(layer->projection), &(layer->map->projection)); + if( layer->project && + strstr(layer->map->projection.args[0], "epsg:3857") && + pj_is_latlong(layer->projection.proj) ) + { + if( rectMapCoordinates.minx < -20037508) + rectMapCoordinates.minx = -20037508; + if( rectMapCoordinates.maxx > 20037508 ) + rectMapCoordinates.maxx = 20037508; + } +#endif + msFree(pInfo->pboundinglines); pInfo->pboundinglines = (lineObj *) msSmallMalloc( sizeof( lineObj ) * 4 ); msFree(pInfo->pboundingpoints); @@ -205,7 +218,6 @@ int msGraticuleLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) pInfo->pboundinglines[0].point[1].y = rectMapCoordinates.maxy; #ifdef USE_PROJ - layer->project = msProjectionsDiffer(&(layer->projection), &(layer->map->projection)); if(layer->project) msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[0]); #endif @@ -273,6 +285,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape) shape->type = MS_SHAPE_LINE; shape->line = (lineObj *) msSmallMalloc(sizeof( lineObj )); shape->line->numpoints = (int) pInfo->maxsubdivides; + shape->line->point = NULL; /* * Subdivide and draw current arc, rendering the arc labels first @@ -287,7 +300,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape) case 0: if(!pInfo->blabelaxes) { /* Bottom */ pInfo->ilabelstate++; - shape->numlines = 0; + msFreeShape(shape); return MS_SUCCESS; } @@ -306,7 +319,11 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape) _FormatLabel( layer, shape, shape->line->point[0].x ); if(_AdjustLabelPosition( layer, shape, posBottom ) != MS_SUCCESS) - return MS_FAILURE; + { + msFreeShape(shape); + pInfo->ilabelstate++; + return MS_SUCCESS; + } pInfo->ilabelstate++; return MS_SUCCESS; @@ -314,7 +331,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape) case 1: if(!pInfo->blabelaxes) { /* Top */ pInfo->ilabelstate++; - shape->numlines = 0; + msFreeShape(shape); return MS_SUCCESS; } @@ -333,7 +350,11 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape) _FormatLabel( layer, shape, shape->line->point[0].x ); if(_AdjustLabelPosition( layer, shape, posTop ) != MS_SUCCESS) - return MS_FAILURE; + { + msFreeShape(shape); + pInfo->ilabelstate++; + return MS_SUCCESS; + } pInfo->ilabelstate++; return MS_SUCCESS; @@ -372,7 +393,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape) case 0: if(!pInfo->blabelaxes) { /* Left side */ pInfo->ilabelstate++; - shape->numlines = 0; + msFreeShape(shape); return MS_SUCCESS; } @@ -391,7 +412,11 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape) _FormatLabel( layer, shape, shape->line->point[0].y ); if(_AdjustLabelPosition( layer, shape, posLeft ) != MS_SUCCESS) - return MS_FAILURE; + { + msFreeShape(shape); + pInfo->ilabelstate++; + return MS_SUCCESS; + } pInfo->ilabelstate++; return MS_SUCCESS; @@ -399,7 +424,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape) case 1: if(!pInfo->blabelaxes) { /* Right side */ pInfo->ilabelstate++; - shape->numlines = 0; + msFreeShape(shape); return MS_SUCCESS; } @@ -418,7 +443,11 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape) _FormatLabel( layer, shape, shape->line->point[0].y ); if(_AdjustLabelPosition( layer, shape, posRight ) != MS_SUCCESS) - return MS_FAILURE; + { + msFreeShape(shape); + pInfo->ilabelstate++; + return MS_SUCCESS; + } pInfo->ilabelstate++; return MS_SUCCESS; @@ -1039,7 +1068,20 @@ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticule #ifdef USE_PROJ if(pLayer->project) + { msProjectShape( &pLayer->projection, &pLayer->map->projection, pShape ); + + /* Poor man detection of reprojection failure */ + if( pj_is_latlong(pLayer->projection.proj) != + pj_is_latlong(pLayer->map->projection.proj) ) + { + if( ptPoint.x == pShape->line->point[0].x && + ptPoint.y == pShape->line->point[0].y ) + { + return MS_FAILURE; + } + } + } #endif if(pLayer->transform) { @@ -1067,8 +1109,8 @@ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticule pShape->line->point[0].y = fabs(rectLabel.maxy - rectLabel.miny) * 2 + 5; break; case posLeft: - pShape->line->point[1].x = 0; - pShape->line->point[0].x = fabs(rectLabel.maxx - rectLabel.minx) * 2 + 5; + pShape->line->point[0].x = 0; + pShape->line->point[1].x = fabs(rectLabel.maxx - rectLabel.minx) * 2 + 5; break; case posRight: pShape->line->point[1].x = pLayer->map->width; @@ -1081,7 +1123,75 @@ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticule #ifdef USE_PROJ if(pLayer->project) + { + /* Clamp coordinates into the validity area of the projection, in the */ + /* particular case of EPSG:3857 (WebMercator) to longlat reprojection */ + if( strstr(pLayer->map->projection.args[0], "epsg:3857") && + pj_is_latlong(pLayer->projection.proj) ) + { + if( !pLayer->map->projection.gt.need_geotransform && + ePosition == posLeft && pShape->line->point[0].x < -20037508) + { + pShape->line->point[1].x = -20037508 + (pShape->line->point[1].x - + pShape->line->point[0].x); + pShape->line->point[0].x = -20037508; + } + else if( pLayer->map->projection.gt.need_geotransform && + ePosition == posLeft && + pLayer->map->projection.gt.geotransform[0] + + pShape->line->point[0].x * + pLayer->map->projection.gt.geotransform[1] + + pShape->line->point[0].y * + pLayer->map->projection.gt.geotransform[2] < -20037508) + { + double y_tmp; + double width = pShape->line->point[1].x - pShape->line->point[0].x; + + y_tmp = pLayer->map->projection.gt.geotransform[3] + + pShape->line->point[0].x * + pLayer->map->projection.gt.geotransform[4] + + pShape->line->point[0].y * + pLayer->map->projection.gt.geotransform[5]; + pShape->line->point[0].x = + pLayer->map->projection.gt.invgeotransform[0] + + -20037508 * pLayer->map->projection.gt.invgeotransform[1] + + y_tmp * pLayer->map->projection.gt.invgeotransform[2]; + pShape->line->point[1].x = pShape->line->point[0].x + width; + } + + if( !pLayer->map->projection.gt.need_geotransform && + ePosition == posRight && pShape->line->point[1].x > 20037508) + { + pShape->line->point[0].x = 20037508 - (pShape->line->point[1].x - + pShape->line->point[0].x); + pShape->line->point[1].x = 20037508; + } + else if( pLayer->map->projection.gt.need_geotransform && + ePosition == posRight && + pLayer->map->projection.gt.geotransform[0] + + pShape->line->point[1].x * + pLayer->map->projection.gt.geotransform[1] + + pShape->line->point[1].y * + pLayer->map->projection.gt.geotransform[2] > 20037508) + { + double y_tmp; + double width = pShape->line->point[1].x - pShape->line->point[0].x; + + y_tmp = pLayer->map->projection.gt.geotransform[3] + + pShape->line->point[1].x * + pLayer->map->projection.gt.geotransform[4] + + pShape->line->point[1].y * + pLayer->map->projection.gt.geotransform[5]; + pShape->line->point[1].x = + pLayer->map->projection.gt.invgeotransform[0] + + 20037508 * pLayer->map->projection.gt.invgeotransform[1] + + y_tmp * pLayer->map->projection.gt.invgeotransform[2]; + pShape->line->point[0].x = pShape->line->point[1].x - width; + } + } + msProjectShape( &pLayer->map->projection, &pLayer->projection, pShape ); + } #endif switch( ePosition ) { diff --git a/maphash.c b/maphash.c index c54860223c..1c27cc8c63 100644 --- a/maphash.c +++ b/maphash.c @@ -187,10 +187,14 @@ int msRemoveHashTable(hashTableObj *table, const char *key) status = MS_SUCCESS; if (prev_tp) { prev_tp->next = tp->next; + msFree(tp->key); + msFree(tp->data); free(tp); break; } else { table->items[hash(key)] = tp->next; + msFree(tp->key); + msFree(tp->data); free(tp); break; } diff --git a/maphttp.c b/maphttp.c index e7a18011b8..249cfb7ddc 100644 --- a/maphttp.c +++ b/maphttp.c @@ -39,7 +39,7 @@ #include "mapthread.h" #include "mapows.h" - +#include "cpl_conv.h" #include #ifndef _WIN32 @@ -113,11 +113,6 @@ void msHTTPCleanup() * Should be called on a new array of httpRequestObj to initialize them * for use with msHTTPExecuteRequest(), etc. * - * Note that users of this module should always allocate and init one - * more instance of httpRequestObj in their array than what they plan to - * use because the terminate_handler() needs the last entry in the array - * to have reqObj->request == NULL - * **********************************************************************/ void msHTTPInitRequestObj(httpRequestObj *pasReqInfo, int numRequests) { @@ -476,7 +471,7 @@ int msHTTPExecuteRequests(httpRequestObj *pasReqInfo, int numRequests, * If set then the value is the full path to the ca-bundle.crt file * e.g. CURL_CA_BUNDLE=/usr/local/share/curl/curl-ca-bundle.crt */ - pszCurlCABundle = getenv("CURL_CA_BUNDLE"); + pszCurlCABundle = CPLGetConfigOption("CURL_CA_BUNDLE", NULL); if (debug) { msDebug("HTTP: Starting to prepare HTTP requests.\n"); diff --git a/mapimageio.c b/mapimageio.c index 95feda23d3..df896c56a0 100644 --- a/mapimageio.c +++ b/mapimageio.c @@ -206,11 +206,16 @@ int saveAsJPEG(mapObj *map, rasterBufferObj *rb, streamInfo *info, cinfo.optimize_coding = TRUE; if( arithmetic || optimized ) { - if (map == NULL || msGetConfigOption(map, "JPEGMEM") == NULL) { - /* If the user doesn't provide a value for JPEGMEM, we want to be sure */ - /* that at least the image size will be used before creating the temporary file */ - cinfo.mem->max_memory_to_use = - MS_MAX(cinfo.mem->max_memory_to_use, cinfo.input_components * rb->width * rb->height); + /* libjpeg turbo 1.5.2 honours max_memory_to_use, but has no backing */ + /* store implementation, so better not set max_memory_to_use ourselves. */ + /* See https://github.com/libjpeg-turbo/libjpeg-turbo/issues/162 */ + if( cinfo.mem->max_memory_to_use > 0 ) { + if (map == NULL || msGetConfigOption(map, "JPEGMEM") == NULL) { + /* If the user doesn't provide a value for JPEGMEM, we want to be sure */ + /* that at least the image size will be used before creating the temporary file */ + cinfo.mem->max_memory_to_use = + MS_MAX(cinfo.mem->max_memory_to_use, cinfo.input_components * rb->width * rb->height); + } } } diff --git a/mapio.c b/mapio.c index 7077e8d034..4327ec6907 100644 --- a/mapio.c +++ b/mapio.c @@ -757,6 +757,126 @@ void msIO_installStdinFromBuffer() &group->stderr_context ); } +/************************************************************************/ +/* msIO_getAndStripStdoutBufferMimeHeaders() */ +/* */ +/************************************************************************/ + +hashTableObj* msIO_getAndStripStdoutBufferMimeHeaders() +{ + /* -------------------------------------------------------------------- */ + /* Find stdout buffer. */ + /* -------------------------------------------------------------------- */ + msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" ); + msIOBuffer *buf; + int start_of_mime_header, current_pos; + hashTableObj* hashTable; + + if( ctx == NULL || ctx->write_channel == MS_FALSE + || strcmp(ctx->label,"buffer") != 0 ) { + msSetError( MS_MISCERR, "Can't identify msIO buffer.", + "msIO_getAndStripStdoutBufferMimeHeaders" ); + return NULL; + } + + buf = (msIOBuffer *) ctx->cbData; + + hashTable = msCreateHashTable(); + + /* -------------------------------------------------------------------- */ + /* Loop over all headers. */ + /* -------------------------------------------------------------------- */ + current_pos = 0; + while( MS_TRUE ) { + int pos_of_column = -1; + char* key, *value; + + start_of_mime_header = current_pos; + while( current_pos < buf->data_offset ) + { + if( buf->data[current_pos] == '\r' ) + { + if( current_pos + 1 == buf->data_offset || + buf->data[current_pos + 1] != '\n' ) + { + pos_of_column = -1; + break; + } + break; + } + if( buf->data[current_pos] == ':' ) + { + pos_of_column = current_pos; + if( current_pos + 1 == buf->data_offset || + buf->data[current_pos + 1] != ' ' ) + { + pos_of_column = -1; + break; + } + } + current_pos++; + } + + if( pos_of_column < 0 || current_pos == buf->data_offset ) { + msSetError( MS_MISCERR, "Corrupt mime headers.", + "msIO_getAndStripStdoutBufferMimeHeaders" ); + msFreeHashTable(hashTable); + return NULL; + } + + key = (char*) malloc( pos_of_column - start_of_mime_header + 1 ); + memcpy( key, buf->data+start_of_mime_header, pos_of_column - start_of_mime_header); + key[pos_of_column - start_of_mime_header] = '\0'; + + value = (char*) malloc( current_pos - (pos_of_column+2) + 1 ); + memcpy( value, buf->data+pos_of_column+2, current_pos - (pos_of_column+2)); + value[current_pos - (pos_of_column+2)] = '\0'; + + msInsertHashTable( hashTable, key, value ); + + msFree( key ); + msFree( value ); + + /* -------------------------------------------------------------------- */ + /* Go to next line. */ + /* -------------------------------------------------------------------- */ + current_pos += 2; + if( current_pos == buf->data_offset ) + { + msSetError( MS_MISCERR, "Corrupt mime headers.", + "msIO_getAndStripStdoutBufferMimeHeaders" ); + msFreeHashTable(hashTable); + return NULL; + } + + /* If next line is a '\r', this is the end of mime headers. */ + if( buf->data[current_pos] == '\r' ) + { + current_pos ++; + if( current_pos == buf->data_offset || + buf->data[current_pos] != '\n' ) + { + msSetError( MS_MISCERR, "Corrupt mime headers.", + "msIO_getAndStripStdoutBufferMimeHeaders" ); + msFreeHashTable(hashTable); + return NULL; + } + current_pos ++; + break; + } + } + + /* -------------------------------------------------------------------- */ + /* Move data to front of buffer, and reset length. */ + /* -------------------------------------------------------------------- */ + memmove( buf->data, buf->data+current_pos, + buf->data_offset - current_pos ); + buf->data[buf->data_offset - current_pos] = '\0'; + buf->data_offset -= current_pos; + + return hashTable; +} + /************************************************************************/ /* msIO_stripStdoutBufferContentType() */ /* */ diff --git a/mapio.h b/mapio.h index f339839d61..cc676be870 100644 --- a/mapio.h +++ b/mapio.h @@ -37,6 +37,7 @@ */ #include +#include "maphash.h" #ifdef __cplusplus extern "C" { @@ -105,7 +106,8 @@ extern "C" { void MS_DLL_EXPORT msIO_Cleanup(void); char MS_DLL_EXPORT *msIO_stripStdoutBufferContentType(void); void MS_DLL_EXPORT msIO_stripStdoutBufferContentHeaders(void); - + hashTableObj MS_DLL_EXPORT *msIO_getAndStripStdoutBufferMimeHeaders(void); + msIOContext *msIO_pushStdoutToBufferAndGetOldContext(void); void msIO_restoreOldStdoutContext(msIOContext *context_to_restore); diff --git a/maplabel.c b/maplabel.c index 87989b7f34..76be835156 100644 --- a/maplabel.c +++ b/maplabel.c @@ -217,6 +217,7 @@ void msCopyTextPath(textPathObj *dst, textPathObj *src) { if(src->bounds.poly) { dst->bounds.poly = msSmallMalloc(sizeof(lineObj)); dst->bounds.poly->numpoints = src->bounds.poly->numpoints; + dst->bounds.poly->point = msSmallMalloc(src->bounds.poly->numpoints * sizeof(pointObj)); for(i=0; ibounds.poly->numpoints; i++) { dst->bounds.poly->point[i] = src->bounds.poly->point[i]; } @@ -273,7 +274,7 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char ts->rotation = l->angle * MS_DEG_TO_RAD; } -int msAddLabelGroup(mapObj *map, imageObj *image, int layerindex, int classindex, shapeObj *shape, pointObj *point, double featuresize) +int msAddLabelGroup(mapObj *map, imageObj *image, layerObj* layer, int classindex, shapeObj *shape, pointObj *point, double featuresize) { int l,s, priority; labelCacheSlotObj *cacheslot; @@ -283,9 +284,12 @@ int msAddLabelGroup(mapObj *map, imageObj *image, int layerindex, int classindex classObj *classPtr=NULL; int numtextsymbols = 0; textSymbolObj **textsymbols, *ts; + int layerindex = layer->index; - layerPtr = (GET_LAYER(map, layerindex)); /* set up a few pointers for clarity */ - classPtr = GET_LAYER(map, layerindex)->class[classindex]; + // We cannot use GET_LAYER here because in drawQuery the drawing may happen + // on a temp layer only. + layerPtr = layer; + classPtr = layer->class[classindex]; if(classPtr->numlabels == 0) return MS_SUCCESS; /* not an error just nothing to do */ diff --git a/maplayer.c b/maplayer.c index 5d6b279991..18bf221d1f 100644 --- a/maplayer.c +++ b/maplayer.c @@ -65,6 +65,13 @@ void msLayerFreeItemInfo(layerObj *layer) return; } layer->vtable->LayerFreeItemInfo(layer); + + /* + * Layer expressions with attribute binding hold a numeric index pointing + * to an iteminfo (node->tokenval.bindval.index). If iteminfo changes, + * an expression may be no longer valid. (#5161) + */ + msLayerFreeExpressions(layer); } int msLayerRestoreFromScaletokens(layerObj *layer) @@ -222,7 +229,8 @@ int msLayerOpen(layerObj *layer) if(layer->tileindex && layer->connectiontype == MS_SHAPEFILE) layer->connectiontype = MS_TILED_SHAPEFILE; - if(layer->type == MS_LAYER_RASTER && layer->connectiontype != MS_WMS) + if(layer->type == MS_LAYER_RASTER && layer->connectiontype != MS_WMS + && layer->connectiontype != MS_KERNELDENSITY) layer->connectiontype = MS_RASTER; if ( ! layer->vtable) { @@ -415,8 +423,6 @@ int msLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) */ void msLayerClose(layerObj *layer) { - int i,j,k; - /* no need for items once the layer is closed */ msLayerFreeItemInfo(layer); if(layer->items) { @@ -426,6 +432,21 @@ void msLayerClose(layerObj *layer) } /* clear out items used as part of expressions (bug #2702) -- what about the layer filter? */ + msLayerFreeExpressions(layer); + + if (layer->vtable) { + layer->vtable->LayerClose(layer); + } + msLayerRestoreFromScaletokens(layer); +} + +/* +** Clear out items used as part of expressions. +*/ +void msLayerFreeExpressions(layerObj *layer) +{ + int i,j,k; + msFreeExpressionTokens(&(layer->filter)); msFreeExpressionTokens(&(layer->cluster.group)); msFreeExpressionTokens(&(layer->cluster.filter)); @@ -439,11 +460,6 @@ void msLayerClose(layerObj *layer) msFreeExpressionTokens(&(layer->class[i]->labels[k]->text)); } } - - if (layer->vtable) { - layer->vtable->LayerClose(layer); - } - msLayerRestoreFromScaletokens(layer); } /* @@ -1549,7 +1565,7 @@ int msLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int int msLayerSupportsSorting(layerObj *layer) { if (layer && ( - (layer->connectiontype == MS_OGR) || (layer->connectiontype == MS_POSTGIS) || (layer->connectiontype == MS_ORACLESPATIAL) + (layer->connectiontype == MS_OGR) || (layer->connectiontype == MS_POSTGIS) || (layer->connectiontype == MS_ORACLESPATIAL) || ((layer->connectiontype == MS_PLUGIN) && (strstr(layer->plugin_library,"msplugin_oracle") != NULL)) ) ) return MS_TRUE; @@ -1865,7 +1881,8 @@ int msInitializeVirtualTable(layerObj *layer) if(layer->tileindex && layer->connectiontype == MS_SHAPEFILE) layer->connectiontype = MS_TILED_SHAPEFILE; - if(layer->type == MS_LAYER_RASTER && layer->connectiontype != MS_WMS) + if(layer->type == MS_LAYER_RASTER && layer->connectiontype != MS_WMS + && layer->connectiontype != MS_KERNELDENSITY) layer->connectiontype = MS_RASTER; switch(layer->connectiontype) { @@ -1888,6 +1905,10 @@ int msInitializeVirtualTable(layerObj *layer) /* WMS should be treated as a raster layer */ return(msRASTERLayerInitializeVirtualTable(layer)); break; + case(MS_KERNELDENSITY): + /* KERNELDENSITY should be treated as a raster layer */ + return(msRASTERLayerInitializeVirtualTable(layer)); + break; case(MS_ORACLESPATIAL): return(msOracleSpatialLayerInitializeVirtualTable(layer)); break; diff --git a/maplegend.c b/maplegend.c index 2dcc91b0fc..4c2d377352 100644 --- a/maplegend.c +++ b/maplegend.c @@ -35,6 +35,54 @@ #define VMARGIN 5 /* margin at top and bottom of legend graphic */ #define HMARGIN 5 /* margin at left and right of legend graphic */ + +static int msDrawGradientSymbol(rendererVTableObj* renderer, + imageObj* image_draw, + double x_center, + double y_center, + int width, + int height, + styleObj* style) +{ + int i, j; + unsigned char *r,*g,*b,*a; + symbolObj symbol; + rasterBufferObj* rb; + symbolStyleObj symbolStyle; + int ret; + + initSymbol(&symbol); + rb = (rasterBufferObj*)calloc(1,sizeof(rasterBufferObj)); + symbol.pixmap_buffer = rb; + rb->type = MS_BUFFER_BYTE_RGBA; + rb->width = width; + rb->height = height; + rb->data.rgba.row_step = rb->width * 4; + rb->data.rgba.pixel_step = 4; + rb->data.rgba.pixels = (unsigned char*)malloc( + rb->width*rb->height*4*sizeof(unsigned char)); + b = rb->data.rgba.b = &rb->data.rgba.pixels[0]; + g = rb->data.rgba.g = &rb->data.rgba.pixels[1]; + r = rb->data.rgba.r = &rb->data.rgba.pixels[2]; + a = rb->data.rgba.a = &rb->data.rgba.pixels[3]; + for( j = 0; j < rb->height; j++ ) + { + for( i = 0; i < rb->width; i++ ) + { + msValueToRange(style, style->minvalue + + (double)i / rb->width * (style->maxvalue - style->minvalue), MS_COLORSPACE_RGB); + b[4*(j * rb->width + i)] = style->color.blue; + g[4*(j * rb->width + i)] = style->color.green; + r[4*(j * rb->width + i)] = style->color.red; + a[4*(j * rb->width + i)] = style->color.alpha; + } + } + INIT_SYMBOL_STYLE(symbolStyle); + ret = renderer->renderPixmapSymbol(image_draw, x_center, y_center, &symbol, &symbolStyle); + msFreeSymbol(&symbol); + return ret; +} + /* * generic function for drawing a legend icon. (added for bug #2348) * renderer specific drawing functions shouldn't be called directly, but through @@ -262,8 +310,22 @@ int msDrawLegendIcon(mapObj *map, layerObj *lp, classObj *theclass, if (theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_NONE || theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT || theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) { - ret = msDrawShadeSymbol(map, image_draw, &box, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor); - if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; + + if (MS_VALID_COLOR(theclass->styles[i]->mincolor)) + { + ret = msDrawGradientSymbol(renderer, + image_draw, + dstX + width / 2., + dstY + height / 2.0, + width - 2 * polygon_contraction, + height - 2 * polygon_contraction, + theclass->styles[i]); + } + else + { + ret = msDrawShadeSymbol(map, image_draw, &box, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor); + } + if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; } else { ret = msDrawTransformedShape(map, image_draw, &box, @@ -325,6 +387,7 @@ int msDrawLegendIcon(mapObj *map, layerObj *lp, classObj *theclass, initTextSymbol(&ts); msPopulateTextSymbolForLabelAndString(&ts,theclass->labels[0],msStrdup("Az"),lp->scalefactor*image_draw->resolutionfactor,image_draw->resolutionfactor, duplicate_always); ts.label->size = height - 1; + ts.rotation = 0; ret = msComputeTextPath(map,&ts); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; textstartpt = get_metrics(&marker,MS_CC,ts.textpath,0,0,0,0,NULL); @@ -394,7 +457,6 @@ int msDrawLegendIcon(mapObj *map, layerObj *lp, classObj *theclass, return ret; } - imageObj *msCreateLegendIcon(mapObj* map, layerObj* lp, classObj* class, int width, int height, int scale_independant) { imageObj *image; @@ -523,7 +585,7 @@ int msLegendCalcSize(mapObj *map, int scale_independent, int *size_x, int *size_ if(*text) { initTextSymbol(&ts); - msPopulateTextSymbolForLabelAndString(&ts,&map->legend.label,msStrdup(text),lp->scalefactor*resolutionfactor,resolutionfactor, 0); + msPopulateTextSymbolForLabelAndString(&ts,&map->legend.label,msStrdup(text),resolutionfactor,resolutionfactor, 0); if(UNLIKELY(MS_FAILURE == msGetTextSymbolSize(map,&ts,&rect))) { freeTextSymbol(&ts); return MS_FAILURE; @@ -638,7 +700,7 @@ imageObj *msDrawLegend(mapObj *map, int scale_independent, map_hittest *hittest) cur = (legendlabel*) msSmallMalloc(sizeof(legendlabel)); initTextSymbol(&cur->ts); if(*text) { - msPopulateTextSymbolForLabelAndString(&cur->ts,&map->legend.label,msStrdup(text),lp->scalefactor*map->resolution/map->defresolution,map->resolution/map->defresolution, 0); + msPopulateTextSymbolForLabelAndString(&cur->ts,&map->legend.label,msStrdup(text),map->resolution/map->defresolution,map->resolution/map->defresolution, 0); if(UNLIKELY(MS_FAILURE == msComputeTextPath(map,&cur->ts))) { ret = MS_FAILURE; goto cleanup; @@ -697,11 +759,13 @@ imageObj *msDrawLegend(mapObj *map, int scale_independent, map_hittest *hittest) pnt.y += cur->height; if(cur->ts.annotext) { - pnt.y -= cur->ts.textpath->bounds.bbox.maxy; - ret = msDrawTextSymbol(map,image,pnt,&cur->ts); + pointObj textPnt = pnt; + textPnt.y -= cur->ts.textpath->bounds.bbox.maxy; + textPnt.y += map->legend.label.offsety; + textPnt.x += map->legend.label.offsetx; + ret = msDrawTextSymbol(map,image,textPnt,&cur->ts); if(UNLIKELY(ret == MS_FAILURE)) goto cleanup; - pnt.y += cur->ts.textpath->bounds.bbox.maxy; freeTextSymbol(&cur->ts); } diff --git a/maplexer.c b/maplexer.c index ef6aa22967..63c7fa2c83 100644 --- a/maplexer.c +++ b/maplexer.c @@ -1,6 +1,6 @@ -#line 2 "/Users/tbonfort/dev/mapserver/maplexer.c" +#line 2 "/home/tbonfort/dev/mapserver/maplexer.c" -#line 4 "/Users/tbonfort/dev/mapserver/maplexer.c" +#line 4 "/home/tbonfort/dev/mapserver/maplexer.c" #define YY_INT_ALIGNED short int @@ -27,8 +27,8 @@ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 35 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 0 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif @@ -66,7 +66,6 @@ typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; -typedef uint64_t flex_uint64_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; @@ -74,7 +73,6 @@ typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; -#endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN @@ -105,6 +103,8 @@ typedef unsigned int flex_uint32_t; #define UINT32_MAX (4294967295U) #endif +#endif /* ! C99 */ + #endif /* ! FLEXINT_H */ #ifdef __cplusplus @@ -161,7 +161,15 @@ typedef unsigned int flex_uint32_t; /* Size of default input buffer. */ #ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else #define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. @@ -187,6 +195,7 @@ extern FILE *msyyin, *msyyout; #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ @@ -221,7 +230,7 @@ struct yy_buffer_state /* Number of characters read into yy_ch_buf, not including EOB * characters. */ - yy_size_t yy_n_chars; + int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to @@ -291,7 +300,7 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* yy_hold_char holds the character lost when msyytext is formed. */ static char yy_hold_char; -static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ +static int yy_n_chars; /* number of characters read into yy_ch_buf */ yy_size_t msyyleng; /* Points to current character in buffer. */ @@ -363,11 +372,17 @@ extern int msyylineno; int msyylineno = 1; extern char *msyytext; +#ifdef yytext_ptr +#undef yytext_ptr +#endif #define yytext_ptr msyytext static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); +#if defined(__GNUC__) && __GNUC__ >= 3 +__attribute__((__noreturn__)) +#endif static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the @@ -375,7 +390,7 @@ static void yy_fatal_error (yyconst char msg[] ); */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ - msyyleng = (yy_size_t) (yy_cp - yy_bp); \ + msyyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; @@ -614,7 +629,7 @@ static yyconst flex_int16_t yy_accept[2005] = 341, 341, 176, 0 } ; -static yyconst flex_int32_t yy_ec[256] = +static yyconst YY_CHAR yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, @@ -646,7 +661,7 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[89] = +static yyconst YY_CHAR yy_meta[89] = { 0, 1, 1, 2, 1, 3, 1, 4, 1, 1, 5, 1, 1, 1, 1, 6, 7, 7, 7, 7, 3, @@ -659,231 +674,231 @@ static yyconst flex_int32_t yy_meta[89] = 1, 1, 1, 1, 1, 1, 1, 1 } ; -static yyconst flex_int16_t yy_base[2025] = +static yyconst flex_uint16_t yy_base[2025] = { 0, 0, 0, 86, 172, 260, 0, 348, 0, 89, 93, - 97, 99, 1016, 4555, 115, 4555, 4555, 0, 944, 115, + 97, 99, 936, 4574, 115, 4574, 4574, 0, 922, 115, 119, 436, 151, 127, 430, 499, 162, 428, 504, 511, 173, 424, 54, 83, 560, 561, 428, 612, 620, 80, - 444, 667, 622, 676, 449, 725, 0, 900, 864, 852, - 4555, 4555, 4555, 98, 116, 126, 145, 173, 456, 195, + 444, 667, 622, 676, 449, 725, 0, 863, 824, 815, + 4574, 4574, 4574, 98, 116, 126, 145, 173, 456, 195, 183, 182, 442, 564, 437, 442, 453, 528, 179, 562, - 502, 730, 576, 669, 676, 509, 501, 629, 516, 745, - 559, 514, 735, 774, 580, 785, 781, 781, 613, 4555, - 254, 549, 878, 847, 883, 840, 595, 704, 823, 861, - - 646, 812, 714, 732, 789, 789, 554, 830, 817, 565, - 685, 835, 837, 827, 680, 838, 839, 723, 738, 871, - 51, 741, 768, 4555, 4555, 723, 771, 757, 0, 762, - 804, 874, 884, 0, 708, 678, 896, 900, 0, 902, - 917, 657, 961, 806, 921, 927, 824, 953, 836, 950, - 850, 917, 874, 957, 0, 880, 898, 886, 933, 957, - 0, 944, 952, 0, 972, 966, 963, 967, 980, 977, - 965, 1012, 974, 1028, 987, 1022, 1000, 1000, 1003, 1030, - 1041, 1015, 1037, 1027, 1040, 1071, 1040, 1039, 1033, 1040, - 1075, 0, 1091, 1039, 0, 1047, 0, 1083, 1074, 1100, - - 1043, 1038, 1083, 1101, 1084, 1085, 1105, 1115, 1116, 1098, - 1131, 1119, 1122, 1118, 1131, 1144, 1145, 1150, 1143, 1183, - 1154, 1144, 1165, 1160, 1173, 1193, 1176, 1157, 1179, 1172, - 1168, 1180, 1201, 1203, 1186, 1215, 1185, 0, 0, 1209, - 0, 1216, 1209, 1216, 1231, 1237, 1221, 1237, 1222, 1224, - 1243, 619, 4555, 586, 584, 524, 1244, 1251, 1251, 1240, - 1260, 1260, 1256, 1248, 1251, 1263, 1270, 1268, 1251, 1253, - 1278, 1271, 1279, 530, 1306, 4555, 1299, 1281, 1285, 1284, - 1267, 1284, 1301, 1301, 1306, 1302, 1316, 1308, 1323, 1329, - 1300, 1331, 1333, 1320, 1329, 1321, 1337, 0, 1326, 1342, - - 1328, 1327, 1349, 1337, 1343, 1364, 1340, 1366, 1362, 1363, - 1372, 1369, 1364, 1377, 4555, 503, 4555, 497, 1398, 1409, - 1405, 1429, 1431, 1437, 4555, 4555, 4555, 4555, 1384, 1403, - 1384, 1405, 1417, 1398, 1416, 1428, 1417, 1431, 1428, 1432, - 1434, 4555, 1440, 1428, 1437, 1429, 4555, 1434, 4555, 1450, - 1435, 1444, 1443, 1444, 1438, 1448, 1450, 403, 1470, 1471, - 1468, 4555, 397, 199, 4555, 4555, 245, 4555, 238, 0, - 4555, 4555, 4555, 1509, 1517, 154, 559, 813, 1466, 0, - 1515, 1526, 915, 932, 1477, 1484, 1481, 1483, 1507, 1504, - 1514, 1522, 1522, 1524, 1517, 1508, 1526, 1513, 1514, 1517, - - 1533, 1518, 1519, 1524, 1524, 1535, 0, 1541, 1522, 1559, - 1522, 1532, 1543, 1548, 1534, 1561, 0, 1563, 1563, 1577, - 1568, 1568, 1569, 1578, 1580, 1573, 1574, 1592, 1583, 0, - 1584, 1585, 1580, 1597, 1581, 1600, 1600, 1597, 1603, 1603, - 1609, 1596, 1612, 1609, 1624, 1625, 1631, 1628, 1639, 1642, - 1639, 1647, 1650, 1635, 1651, 1652, 0, 0, 1647, 1648, - 1690, 1653, 1671, 1659, 1662, 1744, 1668, 1657, 1667, 1695, - 1681, 1701, 1698, 1693, 0, 226, 1713, 1715, 1722, 1703, - 1704, 1706, 1726, 1749, 1728, 1725, 1758, 1752, 1743, 1765, - 1753, 1766, 1754, 1773, 1771, 1785, 1783, 1770, 1781, 1789, - - 1786, 1789, 1802, 1804, 1794, 1805, 1808, 1803, 1815, 1798, - 1809, 0, 1821, 1812, 1809, 1806, 1824, 1805, 1821, 1829, - 1821, 1835, 1832, 1835, 1830, 1844, 1841, 1849, 1839, 0, - 0, 1842, 0, 0, 1847, 4555, 1857, 1853, 1856, 1870, - 1870, 1873, 1875, 1877, 4555, 1873, 1867, 1881, 1872, 1876, - 1886, 1880, 1881, 1876, 4555, 142, 4555, 1878, 1883, 1885, - 1901, 1903, 1902, 1890, 1892, 1908, 1912, 1916, 1915, 1920, - 1926, 1913, 1924, 1919, 1934, 1926, 1933, 1940, 1940, 1945, - 1932, 1944, 1930, 135, 768, 128, 181, 1048, 1163, 1964, - 1962, 1180, 1665, 1960, 1949, 1960, 1959, 1954, 1958, 1976, - - 1973, 1964, 1984, 1967, 1968, 1975, 1984, 1970, 1986, 1992, - 1987, 1991, 4555, 1980, 1985, 1985, 1987, 1984, 2003, 2002, - 2004, 2002, 2014, 2007, 2010, 462, 610, 1670, 4555, 1683, - 1724, 2012, 2013, 2026, 2024, 2044, 158, 2039, 2028, 2036, - 2027, 2049, 2032, 2047, 0, 2048, 2054, 2044, 2039, 2040, - 2043, 2057, 2055, 2061, 2052, 2052, 2062, 2050, 2068, 2080, - 0, 2072, 2086, 2068, 2092, 2088, 2102, 2094, 2104, 2089, - 0, 2106, 2107, 2098, 2095, 2110, 2112, 2117, 0, 2100, - 2102, 2114, 2106, 2110, 2120, 2124, 2110, 2126, 2127, 2112, - 2110, 2126, 2118, 2128, 0, 2145, 2139, 2159, 2142, 2146, - - 2164, 2155, 2153, 2167, 0, 2159, 2174, 2169, 0, 2158, - 2164, 2171, 2177, 2180, 2173, 2183, 2168, 2188, 2187, 2184, - 2173, 2191, 2178, 2179, 2192, 2196, 2202, 2211, 2225, 2226, - 2218, 2228, 2232, 2229, 2227, 2219, 2229, 2227, 0, 2233, - 0, 2243, 2241, 2227, 2240, 2240, 2245, 2234, 2244, 2248, - 2253, 2254, 2248, 2270, 2265, 2256, 2261, 2275, 2272, 2286, - 2276, 2290, 2291, 2272, 2294, 2295, 2283, 2288, 2284, 2305, - 2299, 2297, 2291, 2308, 2309, 2312, 2301, 2312, 2306, 2307, - 2299, 2309, 2304, 2312, 2331, 2323, 2336, 2342, 0, 2346, - 0, 2339, 2338, 2338, 2345, 2340, 0, 2347, 2343, 2362, - - 2346, 2349, 2366, 2366, 2358, 2366, 0, 2371, 2358, 2373, - 2365, 2375, 2369, 2364, 2369, 2379, 2370, 2380, 2388, 2398, - 4555, 2401, 2397, 2398, 2399, 2401, 0, 2406, 0, 2416, - 2404, 2414, 2412, 2420, 2415, 2408, 0, 2415, 2420, 0, - 4555, 2440, 2443, 4555, 2419, 2435, 2432, 2441, 2424, 2439, - 2430, 2438, 2445, 2455, 2442, 2445, 2448, 2464, 2450, 2450, - 2450, 2460, 2467, 2476, 2469, 2462, 2465, 2476, 4555, 2467, - 2477, 2489, 2465, 2473, 4555, 0, 2474, 0, 2502, 2492, - 0, 2487, 2497, 0, 2506, 2492, 2514, 2504, 2506, 2522, - 0, 2521, 2520, 2523, 2512, 2522, 2524, 2525, 2530, 2520, - - 2541, 2543, 0, 2533, 2527, 2529, 2529, 0, 0, 2540, - 0, 2532, 2546, 0, 2534, 2550, 2549, 2545, 2564, 2552, - 0, 2561, 2566, 0, 2583, 2567, 0, 0, 2570, 2584, - 2589, 2571, 2587, 0, 2592, 2582, 0, 2583, 2602, 2581, - 2607, 2606, 2640, 0, 2599, 0, 2596, 2612, 2627, 2614, - 2612, 2628, 2608, 2629, 2649, 2636, 2632, 2640, 2650, 2655, - 2631, 2662, 2652, 2662, 2654, 2667, 2650, 0, 2645, 2668, - 2648, 2654, 2674, 2661, 2658, 2676, 2690, 2666, 2691, 2681, - 2701, 0, 2692, 0, 2707, 2699, 2692, 2693, 2699, 2695, - 2711, 2703, 2698, 2718, 2719, 2708, 2713, 2709, 2713, 2716, - - 2712, 2717, 2718, 2725, 2757, 2736, 2729, 2721, 2749, 2761, - 2744, 2736, 2750, 2742, 2761, 2752, 2755, 2755, 0, 0, - 2775, 2758, 2757, 2765, 2777, 2783, 2775, 0, 2785, 2772, - 2783, 2781, 0, 2793, 2795, 2814, 2781, 0, 2799, 2823, - 2795, 2789, 0, 0, 2795, 2811, 2797, 2817, 2813, 2817, - 0, 4555, 4555, 2817, 2817, 2835, 4555, 4555, 2836, 2838, - 2829, 2838, 2823, 2848, 4555, 2835, 4555, 2845, 0, 2833, - 2853, 2835, 2871, 2860, 2843, 2852, 2875, 2873, 2860, 2873, - 2881, 2886, 2876, 2887, 2888, 2879, 4555, 2896, 2895, 2900, - 2901, 2884, 2901, 2897, 4555, 2905, 4555, 2903, 2905, 2905, - - 2910, 4555, 2902, 2888, 2920, 2919, 2903, 2906, 2929, 2924, - 2920, 2929, 0, 2936, 0, 0, 2931, 0, 2934, 2933, - 2938, 2957, 2947, 0, 2951, 0, 2941, 2944, 2943, 2950, - 2945, 2951, 0, 2962, 2954, 2955, 2966, 0, 2971, 0, - 2968, 0, 2958, 0, 2964, 2979, 2960, 2980, 0, 0, - 2971, 2973, 2999, 2980, 2977, 2985, 0, 2999, 3001, 3013, - 3014, 3014, 3013, 3016, 3019, 3003, 3023, 3010, 3006, 3027, - 3022, 0, 0, 3023, 3014, 3028, 3019, 3020, 3021, 3021, - 3022, 3020, 3042, 3041, 3032, 3050, 3058, 3060, 3049, 3046, - 0, 3055, 0, 3060, 3058, 3061, 3062, 3063, 3061, 3080, - - 3079, 3075, 3083, 3085, 3074, 3071, 3080, 3097, 0, 0, - 3094, 150, 3075, 3082, 3097, 3097, 3079, 3093, 3095, 3090, - 0, 0, 0, 0, 3106, 3110, 3110, 3107, 3122, 3126, - 3117, 3119, 3119, 3127, 3143, 3125, 0, 3132, 0, 3125, - 3144, 3144, 3130, 3150, 3147, 3138, 3149, 3168, 3159, 0, - 0, 3152, 0, 0, 3142, 3144, 3144, 3145, 3162, 3162, - 3153, 3160, 3171, 3187, 3177, 3174, 3198, 3187, 3196, 3184, - 0, 0, 3191, 4555, 3192, 3183, 4555, 3189, 3209, 3197, - 3192, 3212, 3213, 3190, 0, 3196, 4555, 4555, 3197, 3209, - 3205, 3220, 3212, 3213, 4555, 3227, 3205, 3221, 3218, 3231, - - 3230, 4555, 3233, 3244, 3232, 3238, 3242, 4555, 3259, 3258, - 88, 3251, 3259, 3268, 3249, 3266, 3253, 3258, 3269, 3260, - 3271, 0, 3263, 3258, 3264, 3276, 0, 3266, 3282, 0, - 3278, 0, 3284, 3286, 3281, 0, 3278, 0, 3294, 3297, - 3300, 3297, 3302, 3314, 3299, 3322, 3308, 3313, 0, 3321, - 3327, 3319, 3327, 3328, 0, 3325, 3330, 3333, 3319, 3333, - 3315, 3326, 3329, 3332, 0, 3334, 3342, 0, 3343, 3352, - 3336, 3349, 3342, 3352, 3361, 3369, 0, 3366, 3364, 3372, - 3380, 3380, 0, 3377, 3386, 3369, 3383, 3375, 3374, 3390, - 0, 3387, 3385, 3390, 3394, 3388, 0, 3395, 0, 3385, - - 3399, 3394, 3432, 3394, 0, 3414, 3413, 0, 3422, 0, - 3418, 3433, 3417, 3434, 3439, 3431, 3436, 3449, 3452, 3451, - 3448, 3439, 3450, 3442, 3447, 3451, 3459, 3449, 3461, 3451, - 3452, 3470, 3493, 3472, 3473, 3479, 3484, 0, 3496, 3482, - 3486, 3500, 3502, 0, 0, 3491, 3501, 3499, 3501, 3498, - 3507, 3501, 3515, 3510, 3502, 3503, 3551, 3519, 4555, 3506, - 4555, 3512, 3512, 4555, 3517, 3514, 3528, 4555, 3540, 3537, - 3539, 3534, 3551, 3554, 4555, 3557, 3559, 4555, 3558, 3554, - 3553, 3559, 3562, 0, 3558, 3560, 3558, 3567, 3574, 3577, - 3578, 3572, 3589, 3590, 3575, 0, 3584, 3591, 3603, 3595, - - 3597, 3612, 0, 3604, 3615, 3613, 3610, 3618, 0, 3623, - 3623, 3610, 3617, 0, 3618, 3615, 3626, 3622, 3624, 3619, - 3621, 3620, 3624, 3630, 3618, 3619, 3635, 3638, 3653, 3636, - 3653, 3666, 3666, 3655, 3677, 0, 0, 0, 3653, 3667, - 3664, 3679, 3662, 3677, 3682, 3668, 3690, 0, 0, 3680, - 3693, 3681, 3695, 3682, 3690, 3682, 3701, 3688, 3710, 3683, - 3698, 0, 3698, 3687, 0, 3701, 3708, 0, 3715, 3717, - 3726, 0, 3727, 3736, 3723, 3725, 0, 3730, 0, 3731, - 3742, 0, 3736, 3726, 3745, 3736, 3743, 3756, 3738, 3743, - 0, 3737, 0, 3757, 3751, 3760, 0, 0, 0, 3751, - - 3746, 3753, 3764, 3758, 4555, 3775, 3766, 4555, 3777, 0, - 4555, 3782, 4555, 4555, 4555, 3765, 3774, 3785, 4555, 3786, - 3802, 4555, 3794, 3795, 3791, 3794, 0, 3805, 0, 3797, - 0, 3798, 0, 3810, 3799, 0, 3804, 3801, 0, 3800, - 3807, 0, 3813, 3818, 3822, 0, 3811, 0, 0, 3821, - 0, 3815, 0, 0, 3816, 3835, 3824, 3839, 3846, 0, - 3850, 3851, 3846, 3843, 3862, 3859, 3860, 3864, 3863, 3849, - 3869, 0, 3855, 3867, 3867, 3857, 3874, 3877, 3876, 3862, - 3882, 0, 3883, 3880, 3870, 3882, 3878, 3888, 3877, 3892, - 3901, 3893, 3906, 3903, 3892, 3903, 3898, 3899, 3913, 3922, - - 3924, 3918, 3928, 3925, 3919, 3933, 0, 0, 3923, 3919, - 3927, 3929, 3929, 3929, 3940, 0, 0, 0, 3938, 0, - 3950, 0, 3931, 0, 3939, 3940, 3935, 3941, 4555, 3952, - 4555, 3953, 3954, 3966, 3972, 3959, 3959, 3960, 4555, 3975, - 3972, 3968, 0, 3986, 3991, 0, 0, 0, 3973, 3980, - 3986, 0, 0, 3981, 3985, 0, 3983, 0, 3996, 0, - 0, 0, 3986, 4006, 4011, 3995, 4013, 3991, 0, 0, - 4011, 3998, 4013, 4016, 4028, 4016, 4028, 4028, 0, 4030, - 4020, 4032, 4029, 4028, 4045, 4045, 4039, 4028, 0, 4045, - 4040, 4036, 4056, 4047, 4047, 4046, 4048, 4056, 4064, 4072, - - 4056, 4056, 0, 4076, 0, 0, 4058, 0, 4078, 0, - 0, 0, 4065, 0, 4085, 4071, 4078, 4091, 0, 4086, - 4555, 4555, 4555, 4077, 4555, 4555, 4555, 4555, 4555, 4083, - 4095, 0, 4086, 4083, 4088, 0, 4100, 4102, 4099, 4093, - 4099, 0, 4108, 4115, 4124, 4110, 4112, 0, 0, 0, - 0, 4122, 4122, 4133, 0, 0, 4130, 0, 0, 4125, - 4136, 0, 4138, 0, 4144, 4134, 4145, 4134, 4148, 4138, - 4148, 4150, 4154, 0, 4149, 0, 0, 4162, 0, 4152, - 0, 4169, 4155, 4168, 4153, 0, 4164, 4555, 4171, 4163, - 4169, 0, 4166, 4177, 0, 4180, 0, 4173, 4194, 4196, - - 4183, 0, 4194, 4198, 4194, 0, 4188, 4202, 0, 4197, - 4205, 0, 0, 0, 4200, 0, 4193, 4195, 4209, 4213, - 4218, 4224, 4223, 4226, 4215, 0, 4223, 4213, 4235, 4226, - 4238, 0, 0, 0, 4240, 4247, 0, 4227, 4243, 0, - 4255, 0, 0, 0, 4246, 4258, 4260, 4262, 0, 4264, - 4268, 4262, 4259, 4259, 4555, 4274, 64, 4262, 0, 4276, - 4278, 4280, 4282, 0, 4267, 0, 0, 4286, 0, 0, - 4275, 4279, 0, 56, 4555, 0, 4281, 4283, 0, 0, - 4285, 4286, 4289, 0, 4555, 4290, 4291, 4309, 4303, 0, - 4304, 4309, 4320, 4310, 0, 0, 4312, 4311, 4319, 0, - - 4319, 4317, 0, 4555, 4389, 4398, 4407, 4416, 4425, 4429, - 4436, 4445, 4454, 4457, 4466, 4475, 4484, 4493, 4502, 4511, - 4518, 4527, 4536, 4545 + 502, 730, 576, 669, 676, 509, 501, 726, 516, 748, + 559, 514, 738, 777, 580, 773, 792, 782, 613, 4574, + 254, 549, 865, 825, 857, 787, 595, 810, 825, 804, + + 646, 800, 723, 795, 793, 813, 554, 836, 814, 565, + 641, 843, 844, 822, 628, 842, 842, 670, 686, 868, + 51, 696, 757, 4574, 4574, 718, 748, 741, 0, 747, + 749, 882, 723, 0, 720, 678, 878, 900, 0, 903, + 924, 657, 962, 816, 927, 933, 861, 954, 858, 924, + 878, 950, 887, 959, 0, 890, 905, 936, 954, 959, + 0, 944, 947, 0, 974, 968, 965, 969, 998, 1012, + 964, 1012, 975, 1028, 1005, 1022, 1004, 1014, 1020, 1037, + 1040, 1019, 1041, 1031, 1043, 1073, 1047, 1044, 1060, 1044, + 1077, 0, 1093, 1043, 0, 1051, 0, 1087, 1092, 1078, + + 1089, 1085, 1125, 1100, 1111, 1101, 1115, 1138, 1139, 1121, + 1139, 1134, 1129, 1129, 1134, 1147, 1148, 1153, 1146, 1186, + 1157, 1147, 1172, 1164, 1178, 1187, 1179, 1160, 1205, 1201, + 1196, 1212, 1202, 1205, 1204, 1234, 1202, 0, 0, 1211, + 0, 1215, 1204, 1215, 1225, 1236, 1222, 1238, 1234, 1241, + 1261, 619, 4574, 586, 584, 524, 1256, 1263, 1259, 1247, + 1267, 1275, 1263, 1255, 1260, 1271, 1273, 1277, 1254, 1256, + 1281, 1274, 1282, 530, 1292, 4574, 1310, 1286, 1296, 1291, + 1284, 1310, 1316, 1315, 1306, 1313, 1325, 1312, 1328, 1342, + 1307, 1331, 1332, 1321, 1330, 1322, 1338, 0, 1326, 1347, + + 1334, 1335, 1369, 1350, 1349, 1366, 1353, 1379, 1368, 1371, + 1374, 1375, 1368, 1382, 4574, 503, 4574, 497, 1408, 1428, + 1411, 1436, 1434, 1445, 4574, 4574, 4574, 4574, 1410, 1429, + 1410, 1432, 1429, 1431, 1442, 1440, 1429, 1439, 1434, 1438, + 1440, 4574, 1447, 1433, 1443, 1435, 4574, 1439, 4574, 1455, + 1441, 1450, 1453, 1457, 1450, 1456, 1455, 403, 1494, 1495, + 1489, 4574, 397, 199, 4574, 4574, 245, 4574, 238, 0, + 4574, 4574, 4574, 1505, 1520, 154, 559, 755, 1495, 0, + 1524, 1541, 988, 1166, 1501, 1505, 1502, 1502, 1512, 1507, + 1514, 1526, 1526, 1530, 1525, 1517, 1536, 1523, 1526, 1529, + + 1546, 1531, 1532, 1539, 1539, 1552, 0, 1556, 1538, 1566, + 1541, 1548, 1559, 1565, 1555, 1561, 0, 1564, 1565, 1582, + 1572, 1572, 1573, 1584, 1588, 1582, 1585, 1606, 1595, 0, + 1598, 1598, 1593, 1612, 1596, 1617, 1617, 1616, 1619, 1620, + 1624, 1610, 1629, 1624, 1624, 1627, 1636, 1631, 1644, 1646, + 1642, 1653, 1658, 1644, 1661, 1662, 0, 0, 1659, 1660, + 1702, 1665, 1687, 1674, 1676, 1756, 1677, 1667, 1679, 1694, + 1680, 1702, 1702, 1697, 0, 226, 1717, 1721, 1738, 1710, + 1713, 1716, 1738, 1756, 1736, 1735, 1765, 1762, 1755, 1774, + 1755, 1771, 1763, 1781, 1778, 1794, 1793, 1782, 1790, 1803, + + 1798, 1804, 1814, 1816, 1806, 1816, 1819, 1813, 1826, 1808, + 1818, 0, 1829, 1821, 1819, 1817, 1833, 1814, 1828, 1836, + 1830, 1844, 1841, 1843, 1837, 1856, 1848, 1864, 1847, 0, + 0, 1854, 0, 0, 1862, 4574, 1869, 1863, 1866, 1881, + 1880, 1884, 1885, 1887, 4574, 1883, 1876, 1890, 1882, 1887, + 1895, 1889, 1888, 1883, 4574, 142, 4574, 1887, 1892, 1894, + 1909, 1910, 1909, 1899, 1902, 1920, 1921, 1930, 1927, 1935, + 1938, 1925, 1935, 1930, 1944, 1937, 1943, 1950, 1950, 1954, + 1941, 1954, 1941, 135, 878, 128, 181, 1404, 1406, 1967, + 1973, 1695, 1998, 1969, 1958, 1970, 1968, 1964, 1970, 1985, + + 1985, 1976, 1996, 1979, 1980, 1987, 1997, 1985, 2001, 2007, + 2002, 2005, 4574, 1993, 1999, 1998, 2001, 1997, 2015, 2014, + 2016, 2015, 2005, 2022, 2031, 462, 610, 2062, 4574, 2066, + 2069, 2010, 2020, 2038, 2026, 2052, 158, 2052, 2048, 2056, + 2048, 2070, 2053, 2068, 0, 2070, 2075, 2066, 2060, 2060, + 2063, 2076, 2074, 2080, 2071, 2071, 2081, 2071, 2088, 2089, + 0, 2080, 2093, 2075, 2101, 2090, 2110, 2107, 2124, 2109, + 0, 2127, 2128, 2119, 2116, 2132, 2133, 2139, 0, 2121, + 2122, 2134, 2125, 2129, 2139, 2143, 2129, 2145, 2146, 2132, + 2130, 2146, 2138, 2138, 0, 2153, 2146, 2161, 2149, 2155, + + 2178, 2176, 2174, 2189, 0, 2181, 2193, 2192, 0, 2181, + 2185, 2193, 2199, 2200, 2192, 2202, 2187, 2208, 2205, 2203, + 2192, 2211, 2198, 2199, 2199, 2202, 2206, 2215, 2227, 2234, + 2231, 2248, 2253, 2249, 2248, 2240, 2250, 2249, 0, 2255, + 0, 2264, 2262, 2246, 2259, 2257, 2263, 2252, 2263, 2268, + 2273, 2274, 2268, 2280, 2273, 2263, 2268, 2284, 2274, 2308, + 2283, 2302, 2311, 2293, 2314, 2316, 2305, 2309, 2306, 2326, + 2319, 2317, 2310, 2327, 2328, 2331, 2320, 2331, 2325, 2327, + 2319, 2329, 2324, 2322, 2339, 2330, 2343, 2365, 0, 2344, + 0, 2351, 2351, 2359, 2366, 2362, 0, 2369, 2366, 2385, + + 2368, 2370, 2386, 2386, 2377, 2385, 0, 2390, 2377, 2392, + 2384, 2394, 2389, 2384, 2389, 2399, 2380, 2388, 2395, 2405, + 4574, 2410, 2399, 2406, 2412, 2421, 0, 2426, 0, 2437, + 2425, 2435, 2433, 2442, 2436, 2430, 0, 2436, 2440, 0, + 4574, 2458, 2462, 4574, 2441, 2454, 2451, 2460, 2444, 2459, + 2450, 2458, 2455, 2463, 2449, 2452, 2459, 2477, 2466, 2466, + 2467, 2470, 2477, 2489, 2489, 2482, 2486, 2497, 4574, 2488, + 2498, 2511, 2480, 2497, 4574, 0, 2496, 0, 2516, 2509, + 0, 2504, 2514, 0, 2524, 2511, 2523, 2511, 2512, 2528, + 0, 2529, 2532, 2537, 2528, 2538, 2547, 2542, 2547, 2530, + + 2554, 2556, 0, 2552, 2548, 2550, 2550, 0, 0, 2562, + 0, 2555, 2556, 0, 2561, 2579, 2566, 2562, 2582, 2571, + 0, 2570, 2573, 0, 2589, 2573, 0, 0, 2578, 2596, + 2622, 2584, 2605, 0, 2612, 2607, 0, 2605, 2625, 2602, + 2629, 2626, 2662, 0, 2619, 0, 2618, 2637, 2644, 2631, + 2629, 2648, 2628, 2634, 2653, 2640, 2638, 2649, 2674, 2680, + 2661, 2686, 2677, 2687, 2679, 2692, 2676, 0, 2672, 2695, + 2676, 2682, 2702, 2689, 2685, 2693, 2707, 2683, 2711, 2701, + 2711, 0, 2700, 0, 2714, 2708, 2705, 2707, 2715, 2713, + 2732, 2727, 2722, 2742, 2748, 2732, 2738, 2734, 2738, 2741, + + 2738, 2744, 2745, 2753, 2757, 2762, 2756, 2748, 2766, 2764, + 2762, 2758, 2773, 2765, 2773, 2767, 2771, 2771, 0, 0, + 2801, 2775, 2776, 2788, 2806, 2807, 2800, 0, 2810, 2797, + 2808, 2807, 0, 2821, 2823, 2811, 2809, 0, 2827, 2823, + 2825, 2808, 0, 0, 2817, 2833, 2820, 2840, 2825, 2831, + 0, 4574, 4574, 2832, 2834, 2854, 4574, 4574, 2857, 2862, + 2853, 2862, 2852, 2874, 4574, 2861, 4574, 2872, 0, 2858, + 2880, 2862, 2877, 2886, 2870, 2878, 2890, 2889, 2876, 2893, + 2891, 2896, 2884, 2894, 2897, 2892, 4574, 2910, 2911, 2918, + 2922, 2908, 2925, 2921, 4574, 2934, 4574, 2927, 2930, 2930, + + 2935, 4574, 2927, 2582, 2945, 2944, 2929, 2926, 2942, 2937, + 2933, 2943, 0, 2950, 0, 0, 2937, 0, 2943, 2942, + 2945, 2963, 2953, 0, 2959, 0, 2955, 2960, 2961, 2971, + 2969, 2975, 0, 2986, 2983, 2979, 2991, 0, 2996, 0, + 2993, 0, 2983, 0, 2989, 3004, 2986, 3003, 0, 0, + 2995, 2996, 3012, 2993, 2990, 2999, 0, 3013, 3007, 3022, + 3023, 3021, 3019, 3022, 3027, 3017, 3039, 3028, 3027, 3050, + 3047, 0, 0, 3047, 3044, 3053, 3044, 3045, 3046, 3046, + 3047, 3046, 3065, 3065, 3055, 3063, 3071, 3073, 3063, 3060, + 0, 3061, 0, 3069, 3067, 3068, 3068, 3069, 3069, 3094, + + 3095, 3093, 3104, 3109, 3098, 3095, 3109, 3121, 0, 0, + 3119, 150, 3100, 3107, 3122, 3122, 3104, 3119, 3118, 3114, + 0, 0, 0, 0, 3129, 3123, 3123, 3120, 3136, 3140, + 3123, 3128, 3128, 3134, 3149, 3131, 0, 3140, 0, 3139, + 3160, 3162, 3151, 3174, 3171, 3162, 3178, 3181, 3185, 0, + 0, 3178, 0, 0, 3168, 3170, 3170, 3171, 3189, 3189, + 3177, 3183, 3184, 3200, 3191, 3188, 3204, 3196, 3205, 3191, + 0, 0, 3197, 4574, 3198, 3191, 4574, 3203, 3225, 3215, + 3213, 3236, 3237, 3214, 0, 3225, 4574, 4574, 3221, 3234, + 3230, 3245, 3237, 3238, 4574, 3252, 3231, 3244, 3242, 3254, + + 3243, 4574, 3246, 3257, 3246, 3252, 3248, 4574, 3270, 3266, + 88, 3257, 3265, 3274, 3257, 3280, 3269, 3276, 3295, 3286, + 3302, 0, 3294, 3290, 3291, 3303, 0, 3293, 3307, 0, + 3303, 0, 3310, 3309, 3305, 0, 3301, 0, 3307, 3310, + 3313, 3310, 3315, 3324, 3309, 3329, 3317, 3322, 0, 3328, + 3333, 3325, 3335, 3342, 0, 3341, 3348, 3359, 3345, 3364, + 3346, 3358, 3356, 3359, 0, 3361, 3367, 0, 3368, 3378, + 3359, 3373, 3365, 3365, 3374, 3382, 0, 3379, 3377, 3382, + 3390, 3387, 0, 3386, 3395, 3376, 3389, 3381, 3382, 3404, + 0, 3403, 3403, 3416, 3420, 3419, 0, 3419, 0, 3419, + + 3434, 3421, 3439, 3419, 0, 3438, 3438, 0, 3431, 0, + 3428, 3443, 3424, 3441, 3442, 3435, 3443, 3455, 3458, 3459, + 3462, 3455, 3468, 3468, 3473, 3482, 3490, 3481, 3488, 3478, + 3479, 3495, 3498, 3499, 3498, 3502, 3496, 0, 3507, 3493, + 3494, 3508, 3509, 0, 0, 3497, 3507, 3507, 3508, 3505, + 3513, 3507, 3523, 3524, 3518, 3521, 3546, 3550, 4574, 3537, + 4574, 3544, 3539, 4574, 3544, 3542, 3554, 4574, 3563, 3559, + 3550, 3546, 3563, 3566, 4574, 3569, 3566, 4574, 3566, 3561, + 3558, 3567, 3569, 0, 3565, 3566, 3564, 3575, 3594, 3605, + 3606, 3602, 3613, 3615, 3600, 0, 3607, 3609, 3619, 3605, + + 3607, 3622, 0, 3613, 3624, 3622, 3619, 3628, 0, 3633, + 3630, 3617, 3623, 0, 3624, 3621, 3632, 3630, 3631, 3626, + 3627, 3626, 3632, 3650, 3646, 3647, 3665, 3662, 3678, 3661, + 3676, 3684, 3682, 3665, 3687, 0, 0, 0, 3663, 3676, + 3673, 3688, 3671, 3687, 3692, 3675, 3697, 0, 0, 3686, + 3699, 3687, 3701, 3690, 3697, 3689, 3707, 3694, 3733, 3691, + 3716, 0, 3728, 3725, 0, 3728, 3734, 0, 3733, 3733, + 3736, 0, 3737, 3746, 3732, 3734, 0, 3739, 0, 3740, + 3752, 0, 3746, 3733, 3752, 3742, 3749, 3762, 3744, 3751, + 0, 3744, 0, 3764, 3757, 3766, 0, 0, 0, 3759, + + 3766, 3781, 3792, 3788, 4574, 3799, 3791, 4574, 3802, 0, + 4574, 3805, 4574, 4574, 4574, 3783, 3790, 3795, 4574, 3796, + 3812, 4574, 3802, 3803, 3802, 3803, 0, 3815, 0, 3807, + 0, 3805, 0, 3817, 3805, 0, 3810, 3807, 0, 3806, + 3815, 0, 3817, 3824, 3830, 0, 3831, 0, 0, 3849, + 0, 3843, 0, 0, 3843, 3856, 3846, 3861, 3867, 0, + 3866, 3867, 3862, 3859, 3872, 3869, 3870, 3873, 3872, 3858, + 3878, 0, 3865, 3877, 3874, 3864, 3880, 3883, 3882, 3868, + 3890, 0, 3887, 3886, 3878, 3902, 3906, 3916, 3904, 3913, + 3923, 3915, 3927, 3919, 3908, 3919, 3914, 3909, 3923, 3932, + + 3933, 3927, 3937, 3934, 3929, 3943, 0, 0, 3930, 3926, + 3933, 3935, 3935, 3935, 3948, 0, 0, 0, 3942, 0, + 3956, 0, 3939, 0, 3959, 3968, 3963, 3968, 4574, 3973, + 4574, 3975, 3976, 3987, 3988, 3975, 3975, 3976, 4574, 3986, + 3978, 3979, 0, 3997, 4000, 0, 0, 0, 3982, 3989, + 3996, 0, 0, 3991, 3993, 0, 3989, 0, 4001, 0, + 0, 0, 3991, 4011, 4015, 4001, 4021, 4011, 0, 0, + 4033, 4025, 4037, 4034, 4047, 4035, 4047, 4047, 0, 4049, + 4036, 4048, 4045, 4044, 4055, 4055, 4049, 4037, 0, 4054, + 4049, 4045, 4066, 4057, 4055, 4052, 4053, 4061, 4069, 4076, + + 4062, 4064, 0, 4096, 0, 0, 4080, 0, 4105, 0, + 0, 0, 4089, 0, 4103, 4090, 4097, 4110, 0, 4105, + 4574, 4574, 4574, 4096, 4574, 4574, 4574, 4574, 4574, 4098, + 4111, 0, 4103, 4099, 4096, 0, 4107, 4109, 4106, 4100, + 4106, 0, 4117, 4120, 4128, 4114, 4116, 0, 0, 0, + 0, 4122, 4128, 4141, 0, 0, 4149, 0, 0, 4144, + 4157, 0, 4163, 0, 4168, 4152, 4163, 4152, 4166, 4157, + 4167, 4169, 4170, 0, 4165, 0, 0, 4178, 0, 4168, + 0, 4179, 4164, 4176, 4161, 0, 4172, 4574, 4179, 4165, + 4180, 0, 4179, 4182, 0, 4184, 0, 4173, 4200, 4215, + + 4202, 0, 4215, 4218, 4217, 0, 4205, 4219, 0, 4214, + 4222, 0, 0, 0, 4217, 0, 4211, 4212, 4225, 4228, + 4233, 4239, 4238, 4239, 4225, 0, 4232, 4221, 4252, 4233, + 4244, 0, 0, 0, 4249, 4250, 0, 4232, 4247, 0, + 4255, 0, 0, 0, 4252, 4277, 4278, 4281, 0, 4282, + 4287, 4279, 4276, 4276, 4574, 4291, 64, 4279, 0, 4294, + 4295, 4296, 4297, 0, 4282, 0, 0, 4301, 0, 0, + 4290, 4292, 0, 56, 4574, 0, 4293, 4294, 0, 0, + 4295, 4295, 4298, 0, 4574, 4297, 4300, 4312, 4307, 0, + 4308, 4309, 4326, 4329, 0, 0, 4330, 4330, 4337, 0, + + 4336, 4336, 0, 4574, 4408, 4417, 4426, 4435, 4444, 4448, + 4455, 4464, 4473, 4476, 4485, 4494, 4503, 4512, 4521, 4530, + 4537, 4546, 4555, 4564 } ; static yyconst flex_int16_t yy_def[2025] = @@ -1113,7 +1128,7 @@ static yyconst flex_int16_t yy_def[2025] = 2004, 2004, 2004, 2004 } ; -static yyconst flex_int16_t yy_nxt[4644] = +static yyconst flex_uint16_t yy_nxt[4663] = { 0, 14, 15, 16, 15, 15, 14, 17, 18, 14, 17, 19, 14, 14, 14, 20, 21, 22, 23, 23, 14, @@ -1187,448 +1202,450 @@ static yyconst flex_int16_t yy_nxt[4644] = 281, 197, 343, 164, 282, 201, 149, 270, 305, 202, 205, 206, 221, 212, 248, 232, 249, 213, 207, 233, 208, 214, 209, 234, 215, 210, 211, 216, 326, 235, - 217, 627, 236, 875, 289, 290, 255, 327, 255, 237, + 217, 627, 236, 875, 344, 351, 255, 327, 255, 237, 253, 205, 206, 379, 212, 248, 232, 249, 213, 207, 233, 208, 214, 209, 234, 215, 210, 211, 216, 136, - 235, 217, 223, 236, 224, 289, 290, 225, 226, 173, - - 237, 238, 227, 174, 283, 284, 228, 286, 344, 229, - 239, 230, 240, 287, 231, 285, 241, 351, 242, 136, - 243, 321, 321, 223, 133, 224, 133, 133, 225, 226, - 173, 322, 238, 227, 174, 283, 284, 228, 286, 344, - 229, 239, 230, 240, 287, 231, 285, 241, 351, 242, - 329, 243, 246, 247, 330, 155, 248, 156, 249, 331, - 250, 356, 322, 297, 279, 251, 368, 280, 292, 357, - 161, 298, 293, 208, 841, 332, 139, 368, 299, 300, - 366, 329, 139, 246, 247, 330, 155, 248, 156, 249, - 331, 250, 356, 371, 297, 279, 251, 301, 280, 292, - - 357, 161, 298, 293, 208, 302, 332, 139, 310, 299, - 300, 303, 311, 139, 304, 306, 307, 314, 312, 585, - 335, 313, 349, 139, 371, 139, 333, 308, 301, 334, - 378, 378, 309, 328, 336, 372, 302, 380, 323, 310, - 320, 320, 303, 311, 341, 304, 306, 307, 314, 312, - 324, 335, 313, 338, 139, 385, 139, 333, 308, 342, - 334, 339, 345, 309, 315, 336, 372, 349, 380, 352, - 340, 350, 346, 353, 348, 341, 354, 347, 390, 355, - 373, 324, 325, 373, 338, 133, 385, 133, 133, 318, - 342, 317, 339, 345, 393, 315, 316, 359, 349, 315, - - 352, 340, 350, 346, 353, 348, 360, 354, 347, 390, - 355, 396, 361, 374, 374, 145, 399, 138, 138, 140, - 140, 400, 362, 375, 373, 393, 401, 146, 359, 141, - 376, 377, 384, 384, 378, 378, 256, 360, 381, 381, - 383, 383, 396, 361, 384, 384, 255, 399, 382, 384, - 384, 253, 400, 394, 375, 136, 402, 401, 146, 395, - 141, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 391, 403, 144, 386, 382, - 142, 142, 387, 142, 394, 397, 392, 402, 407, 388, - 395, 404, 405, 406, 408, 389, 409, 411, 412, 398, - - 410, 413, 416, 417, 414, 418, 391, 403, 421, 386, - 142, 142, 142, 387, 142, 2004, 397, 392, 415, 407, - 388, 424, 404, 405, 406, 408, 389, 409, 411, 412, - 398, 410, 413, 416, 417, 414, 418, 429, 430, 421, - 431, 142, 142, 142, 142, 142, 142, 142, 142, 415, - 419, 422, 424, 432, 420, 423, 425, 436, 426, 427, - 437, 438, 428, 439, 433, 589, 589, 444, 429, 430, - 445, 431, 434, 446, 448, 456, 457, 468, 435, 469, - 447, 419, 422, 2004, 432, 420, 423, 425, 436, 426, - 427, 437, 438, 428, 439, 433, 440, 441, 444, 449, - - 462, 445, 442, 434, 446, 448, 456, 457, 468, 435, - 469, 447, 474, 443, 453, 450, 463, 451, 470, 454, - 455, 458, 452, 459, 460, 475, 471, 440, 441, 461, - 449, 462, 476, 442, 464, 465, 466, 472, 477, 478, - 479, 473, 467, 474, 443, 453, 450, 463, 451, 470, - 454, 455, 458, 452, 459, 460, 475, 471, 480, 481, - 461, 482, 483, 476, 484, 464, 465, 466, 472, 477, - 478, 479, 473, 467, 485, 486, 489, 491, 487, 492, - 589, 589, 490, 500, 493, 488, 2004, 501, 502, 480, - 481, 2004, 482, 483, 503, 484, 504, 593, 593, 508, - - 509, 512, 510, 513, 514, 485, 486, 489, 491, 487, - 492, 494, 495, 490, 500, 493, 488, 496, 501, 502, - 520, 497, 498, 524, 499, 503, 511, 504, 505, 506, - 508, 509, 512, 510, 513, 514, 515, 517, 521, 518, - 525, 507, 494, 495, 526, 519, 522, 516, 496, 527, - 528, 520, 497, 498, 524, 499, 529, 511, 523, 505, - 506, 530, 531, 532, 533, 534, 535, 515, 517, 521, - 518, 525, 507, 537, 538, 526, 519, 522, 516, 539, - 527, 528, 540, 541, 542, 544, 545, 529, 546, 523, - 547, 550, 530, 531, 532, 533, 534, 535, 548, 551, - - 552, 553, 554, 555, 537, 538, 391, 543, 558, 561, - 539, 549, 562, 540, 541, 542, 544, 545, 559, 546, - 560, 547, 550, 275, 275, 414, 2004, 417, 387, 548, - 551, 552, 553, 554, 555, 388, 564, 391, 543, 558, - 561, 389, 549, 562, 419, 435, 566, 569, 563, 559, - 425, 560, 565, 427, 567, 570, 414, 276, 417, 387, - 442, 454, 571, 464, 471, 572, 388, 564, 573, 574, - 482, 568, 389, 575, 490, 419, 435, 566, 569, 563, - 576, 425, 498, 565, 427, 567, 570, 578, 579, 510, - 577, 442, 454, 571, 464, 471, 572, 580, 581, 573, - - 574, 482, 568, 520, 575, 490, 517, 582, 583, 516, - 317, 576, 2004, 498, 519, 321, 321, 2004, 578, 579, - 510, 577, 321, 321, 323, 322, 320, 320, 580, 581, - 594, 595, 322, 596, 520, 599, 324, 517, 582, 583, - 516, 317, 588, 588, 600, 519, 589, 589, 590, 590, - 592, 592, 597, 598, 593, 593, 322, 601, 591, 602, - 603, 594, 595, 322, 596, 604, 599, 324, 605, 606, - 607, 608, 610, 611, 612, 600, 613, 614, 615, 616, - 617, 620, 609, 597, 598, 618, 621, 619, 601, 591, - 602, 603, 622, 623, 624, 2004, 604, 629, 625, 605, - - 606, 607, 608, 610, 611, 612, 632, 613, 614, 615, - 616, 617, 620, 609, 633, 634, 618, 621, 619, 362, - 635, 362, 362, 622, 623, 624, 374, 374, 629, 625, - 376, 376, 381, 381, 628, 628, 375, 632, 636, 630, - 630, 637, 382, 631, 631, 633, 634, 638, 639, 640, - 641, 635, 642, 643, 644, 645, 646, 647, 648, 649, - 650, 651, 652, 653, 656, 657, 660, 375, 2004, 636, - 661, 654, 637, 382, 662, 663, 664, 655, 638, 639, - 640, 641, 658, 642, 643, 644, 645, 646, 647, 648, - 649, 650, 651, 652, 653, 656, 657, 660, 665, 659, - - 666, 661, 654, 667, 668, 662, 663, 664, 655, 669, - 670, 671, 672, 658, 674, 675, 676, 677, 679, 680, - 673, 681, 682, 683, 684, 685, 686, 678, 687, 665, - 659, 666, 688, 689, 667, 668, 691, 690, 692, 693, - 669, 670, 671, 672, 694, 674, 675, 676, 677, 679, - 680, 673, 681, 682, 683, 684, 685, 686, 678, 687, - 695, 696, 697, 688, 689, 699, 700, 691, 690, 692, - 693, 701, 698, 702, 703, 694, 704, 705, 706, 707, - 708, 709, 593, 593, 721, 2004, 724, 628, 628, 725, - 2004, 695, 696, 697, 722, 736, 699, 700, 723, 737, - - 631, 631, 701, 698, 702, 703, 738, 704, 705, 706, - 707, 708, 709, 710, 711, 721, 712, 724, 713, 714, - 725, 715, 739, 740, 716, 722, 736, 717, 741, 723, - 737, 718, 719, 742, 743, 720, 2004, 738, 745, 2004, - 746, 631, 631, 749, 710, 711, 750, 712, 751, 713, - 714, 752, 715, 739, 740, 716, 747, 755, 717, 741, - 748, 756, 718, 719, 742, 743, 720, 726, 727, 745, - 728, 746, 729, 730, 749, 731, 753, 750, 732, 751, - 761, 757, 752, 759, 754, 733, 734, 747, 755, 735, - 762, 748, 756, 764, 760, 765, 766, 763, 726, 727, - - 767, 728, 768, 729, 730, 758, 731, 753, 769, 732, - 770, 761, 757, 771, 759, 754, 733, 734, 772, 773, - 735, 762, 774, 775, 764, 760, 765, 766, 763, 776, - 777, 767, 779, 768, 780, 781, 758, 782, 783, 769, - 784, 770, 778, 785, 771, 786, 787, 788, 789, 772, - 773, 790, 791, 774, 775, 792, 793, 794, 795, 796, - 776, 777, 797, 779, 802, 780, 781, 798, 782, 783, - 800, 784, 799, 778, 785, 801, 786, 787, 788, 789, - 803, 805, 790, 791, 806, 807, 792, 793, 794, 795, - 796, 808, 804, 797, 809, 802, 810, 811, 798, 812, - - 813, 800, 814, 799, 815, 816, 801, 817, 818, 819, - 820, 803, 805, 821, 822, 806, 807, 823, 824, 825, - 826, 654, 808, 804, 827, 809, 658, 810, 811, 828, - 812, 813, 673, 814, 829, 815, 816, 830, 817, 818, - 819, 820, 689, 831, 821, 822, 697, 833, 823, 824, - 825, 826, 654, 723, 834, 827, 832, 658, 747, 835, - 828, 753, 836, 673, 759, 829, 777, 837, 830, 838, - 839, 840, 799, 689, 831, 842, 842, 697, 833, 843, - 843, 590, 590, 844, 723, 834, 845, 832, 846, 747, - 835, 591, 753, 836, 847, 759, 848, 777, 837, 849, - - 838, 839, 840, 799, 850, 851, 852, 853, 854, 855, - 856, 857, 858, 859, 844, 860, 861, 845, 862, 846, - 863, 864, 591, 865, 866, 847, 867, 848, 868, 869, - 849, 870, 871, 874, 2004, 850, 851, 852, 853, 854, - 855, 856, 857, 858, 859, 873, 860, 861, 876, 862, - 877, 863, 864, 878, 865, 866, 872, 867, 362, 868, - 869, 362, 870, 871, 874, 362, 879, 880, 882, 883, - 884, 885, 886, 887, 888, 889, 873, 890, 892, 876, - 893, 877, 894, 895, 878, 896, 898, 872, 899, 900, - 901, 903, 902, 904, 897, 905, 891, 879, 880, 882, - - 883, 884, 885, 886, 887, 888, 889, 906, 890, 892, - 907, 893, 908, 894, 895, 909, 896, 898, 910, 899, - 900, 901, 903, 902, 904, 897, 905, 891, 911, 912, - 913, 914, 915, 916, 917, 918, 919, 920, 906, 921, - 922, 907, 923, 908, 924, 925, 909, 926, 927, 910, - 928, 929, 930, 931, 932, 933, 934, 935, 936, 911, - 912, 913, 914, 915, 916, 917, 918, 919, 920, 937, - 921, 922, 938, 923, 939, 924, 925, 942, 926, 927, - 943, 928, 929, 930, 931, 932, 933, 934, 935, 936, - 940, 944, 945, 946, 947, 948, 951, 941, 952, 949, - - 937, 953, 954, 938, 955, 939, 950, 956, 942, 957, - 958, 943, 959, 960, 963, 964, 965, 966, 967, 961, - 968, 940, 944, 945, 946, 947, 948, 951, 941, 952, - 949, 962, 953, 954, 969, 955, 970, 950, 956, 971, - 957, 958, 972, 959, 960, 963, 964, 965, 966, 967, - 961, 968, 973, 974, 975, 976, 980, 977, 981, 982, - 983, 984, 962, 978, 985, 969, 986, 970, 987, 989, - 971, 990, 988, 972, 991, 979, 992, 993, 994, 995, - 996, 997, 998, 973, 974, 975, 976, 980, 977, 981, - 982, 983, 984, 999, 978, 985, 1000, 986, 1001, 987, - - 989, 1002, 990, 988, 1003, 991, 979, 992, 993, 994, - 995, 996, 997, 998, 1004, 1005, 1007, 1008, 1009, 1010, - 1006, 1011, 1012, 1013, 999, 1014, 1015, 1000, 1016, 1001, - 1017, 1018, 1002, 1019, 1020, 1003, 1021, 1022, 1023, 1024, - 1025, 1026, 1027, 1028, 1029, 1004, 1005, 1007, 1008, 1009, - 1010, 1006, 1011, 1012, 1013, 1030, 1014, 1015, 1031, 1016, - 1032, 1017, 1018, 1033, 1019, 1020, 1038, 1021, 1022, 1023, - 1024, 1025, 1026, 1027, 1028, 1029, 1034, 1036, 1039, 1040, - 1035, 1041, 1042, 1043, 1044, 1045, 1030, 1037, 1046, 1031, - 1047, 1032, 1048, 1049, 1033, 1050, 1051, 1038, 1052, 1053, - - 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1034, 1036, 1039, - 1040, 1035, 1041, 1042, 1043, 1044, 1045, 1061, 1037, 1046, - 1062, 1047, 1063, 1048, 1049, 1064, 1050, 1051, 1065, 1052, - 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1066, 1067, - 1068, 1069, 1070, 1071, 1072, 940, 1073, 987, 1061, 1074, - 1075, 1062, 1076, 1063, 1077, 1078, 1064, 843, 843, 1065, - 843, 843, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1066, - 1067, 1068, 1069, 1070, 1071, 1072, 940, 1073, 987, 1086, - 1074, 1075, 1087, 1076, 1088, 1077, 1078, 1089, 1090, 1091, - 1092, 1093, 1094, 1079, 1080, 1081, 1082, 1083, 1084, 1085, - - 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 2004, - 1086, 1106, 1104, 1087, 1107, 1088, 362, 1105, 1089, 1090, - 1091, 1092, 1093, 1094, 362, 1108, 1109, 1110, 1111, 1112, - 1113, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, - 362, 1114, 1106, 1104, 1115, 1107, 1116, 1117, 1118, 1119, - 1121, 1120, 1122, 1123, 1126, 1127, 1108, 1109, 1110, 1111, - 1112, 1113, 1124, 1128, 1129, 1125, 1130, 1131, 1132, 1133, - 1134, 1135, 1114, 1136, 1139, 1115, 1140, 1116, 1117, 1118, - 1119, 1121, 1120, 1122, 1123, 1126, 1127, 1137, 1138, 1141, - 1142, 1143, 1144, 1124, 1128, 1129, 1125, 1130, 1131, 1132, - - 1133, 1134, 1135, 1145, 1136, 1139, 1146, 1140, 1147, 1148, - 1149, 1150, 1157, 1158, 1151, 1159, 1160, 1162, 1137, 1138, - 1141, 1142, 1143, 1144, 1152, 1163, 1161, 1153, 1154, 1164, - 1165, 1155, 1156, 1166, 1145, 1172, 1173, 1146, 1174, 1147, - 1148, 1149, 1150, 1157, 1158, 1151, 1159, 1160, 1162, 2004, - 1175, 1176, 1177, 1178, 1179, 1152, 1163, 1161, 1153, 1154, - 1164, 1165, 1155, 1156, 1166, 1167, 1172, 1173, 1168, 1174, - 1180, 1169, 1181, 1182, 1183, 1170, 1184, 1185, 1186, 1187, - 1171, 1175, 1176, 1177, 1178, 1179, 1188, 1189, 1190, 1191, - 1192, 1193, 1194, 1195, 1196, 1197, 1167, 1198, 1199, 1168, - - 1200, 1180, 1169, 1181, 1182, 1183, 1170, 1184, 1185, 1186, - 1187, 1171, 1201, 1202, 1203, 1204, 1205, 1188, 1189, 1190, - 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1206, 1198, 1199, - 1207, 1200, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, - 1216, 1217, 1218, 1201, 1202, 1203, 1204, 1205, 1219, 1220, - 1221, 1222, 1223, 1224, 1225, 1226, 1227, 2004, 1206, 1230, - 1231, 1207, 1232, 1208, 1209, 1210, 1211, 1212, 1213, 1214, - 1215, 1216, 1217, 1218, 1233, 1236, 1237, 1238, 1239, 1219, - 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1234, - 1230, 1231, 1240, 1232, 1241, 1242, 1235, 1229, 1243, 1244, - - 1247, 1245, 1248, 1249, 1250, 1233, 1236, 1237, 1238, 1239, - 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1246, 1258, 1228, - 1234, 1261, 1262, 1240, 1265, 1241, 1242, 1235, 1229, 1243, - 1244, 1247, 1245, 1248, 1249, 1250, 1266, 1267, 1268, 1269, - 1270, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1246, 1258, - 1259, 1263, 1261, 1262, 1271, 1265, 1260, 1272, 1273, 1274, - 1275, 1264, 1277, 1278, 1279, 1280, 1281, 1266, 1267, 1268, - 1269, 1270, 1282, 1283, 1119, 1138, 1120, 1276, 1151, 1161, - 2004, 1259, 1263, 1284, 1224, 1271, 1285, 1260, 1272, 1273, - 1274, 1275, 1264, 1277, 1278, 1279, 1280, 1281, 1286, 1287, - - 1288, 1289, 1169, 1282, 1283, 1119, 1138, 1120, 1276, 1151, - 1161, 1171, 1290, 1291, 1284, 1224, 1292, 1285, 1293, 1294, - 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1286, - 1287, 1288, 1289, 1169, 1304, 1305, 1306, 1307, 1308, 362, - 1309, 1312, 1171, 1290, 1291, 1310, 1311, 1292, 1313, 1293, - 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, - 1314, 1315, 1316, 1317, 1318, 1304, 1305, 1306, 1307, 1308, - 362, 362, 1312, 1319, 1320, 1321, 1310, 1311, 1322, 1313, - 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, - 1333, 1314, 1315, 1316, 1317, 1318, 1334, 1335, 1336, 1337, - - 1338, 1339, 1340, 1341, 1319, 1320, 1321, 1342, 1343, 1322, - 1344, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, - 1332, 1333, 1345, 1346, 1347, 1348, 1349, 1334, 1335, 1336, - 1337, 1338, 1339, 1340, 1341, 1350, 1351, 1352, 1342, 1343, - 1353, 1344, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1363, - 1361, 1364, 1365, 1345, 1346, 1347, 1348, 1349, 1362, 1366, - 1367, 1368, 1369, 1370, 1371, 1372, 1350, 1351, 1352, 1373, - 1374, 1353, 1375, 1354, 1355, 1356, 1357, 1358, 1359, 1360, - 1363, 1361, 1364, 1365, 1376, 1377, 1378, 1379, 1380, 1362, - 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1381, 1382, 1383, - - 1373, 1374, 1384, 1375, 1385, 1386, 1387, 1388, 1389, 1390, - 1391, 1392, 1393, 1394, 1395, 1376, 1377, 1378, 1379, 1380, - 1396, 1397, 1399, 1400, 1401, 1402, 1403, 1404, 1381, 1382, - 1383, 1405, 1406, 1384, 1407, 1385, 1386, 1387, 1388, 1389, - 1390, 1391, 1392, 1393, 1394, 1395, 1408, 1409, 1410, 1411, - 1412, 1396, 1397, 1399, 1400, 1401, 1402, 1403, 1404, 1413, - 1414, 1415, 1405, 1406, 1416, 1407, 1417, 1418, 1419, 1420, - 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1408, 1409, 1410, - 1411, 1412, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, - 1413, 1414, 1415, 1428, 1438, 1416, 1439, 1417, 1418, 1419, - - 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1440, 1429, - 1441, 1442, 1443, 1430, 1431, 1432, 1433, 1434, 1435, 1436, - 1437, 1444, 1445, 1446, 1428, 1438, 1447, 1439, 1448, 1449, - 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1440, - 1429, 1441, 1442, 1443, 1459, 1460, 1461, 1462, 1463, 1464, - 1465, 1466, 1444, 1445, 1446, 1467, 1468, 1447, 1469, 1448, - 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, - 1470, 1471, 1472, 1473, 1474, 1459, 1460, 1461, 1462, 1463, - 1464, 1465, 1466, 1475, 1476, 1477, 1467, 1468, 1479, 1469, - 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489, - - 1490, 1470, 1471, 1472, 1473, 1474, 1491, 1492, 1493, 362, - 362, 1494, 1495, 1496, 1475, 1476, 1477, 1497, 1498, 1479, - 1499, 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1488, - 1489, 1490, 1500, 1501, 1502, 1503, 1504, 1491, 1492, 1493, - 1505, 1506, 1494, 1495, 1496, 1507, 1508, 1509, 1497, 1498, - 1510, 1499, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, - 1519, 1520, 1521, 1500, 1501, 1502, 1503, 1504, 1522, 1523, - 1524, 1505, 1506, 1525, 1526, 1527, 1507, 1508, 1509, 1528, - 1529, 1510, 1530, 1511, 1512, 1513, 1514, 1515, 1516, 1517, - 1518, 1519, 1520, 1521, 1531, 1532, 1533, 1534, 1535, 1522, - - 1523, 1524, 1536, 1537, 1525, 1526, 1527, 1538, 1539, 1540, - 1528, 1529, 1541, 1530, 1542, 1543, 1544, 1545, 1546, 1547, - 1548, 1549, 1550, 1553, 1554, 1531, 1532, 1533, 1534, 1535, - 1551, 1556, 1552, 1536, 1537, 1562, 2004, 1563, 1538, 1539, - 1540, 1564, 2004, 1541, 1555, 1542, 1543, 1544, 1545, 1546, - 1547, 1548, 1549, 1550, 1553, 1554, 1557, 1558, 1565, 1566, - 1567, 1551, 1556, 1552, 1568, 1569, 1562, 1559, 1563, 1560, - 1570, 1571, 1564, 1561, 1572, 1555, 1573, 1574, 1575, 1576, - 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1557, 1558, 1565, - 1566, 1567, 1584, 1585, 1586, 1568, 1569, 1587, 1559, 1590, - - 1560, 1570, 1571, 1591, 1561, 1572, 1592, 1573, 1574, 1575, - 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1588, 1593, - 1589, 1594, 1595, 1584, 1585, 1586, 1596, 1597, 1587, 1598, - 1590, 1599, 1600, 1601, 1591, 1602, 1603, 1592, 1604, 1605, - 1606, 1607, 1608, 1609, 2004, 2004, 1610, 1611, 1612, 1588, - 1593, 1589, 1594, 1595, 1613, 1614, 1615, 1596, 1597, 1616, - 1598, 2004, 1599, 1600, 1601, 1617, 1602, 1603, 1618, 1604, - 1605, 1606, 1607, 1608, 1609, 1557, 1558, 1610, 1611, 1612, - 1619, 1620, 1621, 1622, 1623, 1613, 1614, 1615, 1560, 1625, - 1616, 1626, 1561, 1624, 1627, 1628, 1617, 1629, 1630, 1618, - - 1631, 1632, 1633, 1634, 1635, 1636, 1557, 1558, 362, 1637, - 362, 1619, 1620, 1621, 1622, 1623, 1638, 1639, 1640, 1560, - 1625, 1641, 1626, 1561, 1624, 1627, 1628, 1642, 1629, 1630, - 1643, 1631, 1632, 1633, 1634, 1635, 1636, 1644, 1645, 1646, - 1637, 1647, 1648, 1649, 1650, 1651, 1652, 1638, 1639, 1640, - 1653, 1654, 1641, 1655, 1656, 1657, 1658, 1659, 1642, 1660, - 1661, 1643, 1662, 1663, 1664, 1665, 1666, 1667, 1644, 1645, - 1646, 1668, 1647, 1648, 1649, 1650, 1651, 1652, 1669, 1670, - 1671, 1653, 1654, 1672, 1655, 1656, 1657, 1658, 1659, 1673, - 1660, 1661, 1674, 1662, 1663, 1664, 1665, 1666, 1667, 1675, - - 1676, 1677, 1668, 1678, 1679, 1680, 1681, 1682, 1683, 1669, - 1670, 1671, 1684, 1685, 1672, 1686, 1687, 1688, 1689, 1690, - 1673, 1691, 1692, 1674, 1693, 1694, 1697, 1700, 1701, 1698, - 1675, 1676, 1677, 1695, 1678, 1679, 1680, 1681, 1682, 1683, - 1702, 1696, 1703, 1684, 1685, 1699, 1686, 1687, 1688, 1689, - 1690, 1704, 1691, 1692, 1705, 1693, 1694, 1697, 1700, 1701, - 1698, 1706, 1707, 1708, 1695, 1709, 1710, 1711, 1712, 1713, - 1714, 1702, 1696, 1703, 1715, 1716, 1699, 1717, 1718, 1719, - 1720, 1721, 1704, 1722, 1723, 1705, 1724, 1725, 1726, 1727, - 1728, 1729, 1706, 1707, 1708, 1730, 1709, 1710, 1711, 1712, - - 1713, 1714, 1731, 1732, 1733, 1715, 1716, 1734, 1717, 1718, - 1719, 1720, 1721, 1735, 1722, 1723, 1736, 1724, 1725, 1726, - 1727, 1728, 1729, 1737, 1738, 1739, 1730, 1742, 1740, 1741, - 1743, 1744, 1745, 1731, 1732, 1733, 1746, 1747, 1734, 1748, - 1749, 1750, 1751, 1752, 1735, 362, 362, 1736, 1753, 1754, - 1755, 1756, 1757, 1758, 1737, 1738, 1739, 1759, 1742, 1740, - 1741, 1743, 1744, 1745, 1760, 1761, 1762, 1746, 1747, 1763, - 1748, 1749, 1750, 1751, 1752, 1764, 1765, 1766, 1767, 1753, - 1754, 1755, 1756, 1757, 1758, 1768, 1769, 1770, 1759, 1771, - 1772, 1773, 1774, 1775, 1776, 1760, 1761, 1762, 1777, 1778, - - 1763, 1779, 1780, 1781, 1782, 1783, 1764, 1765, 1766, 1767, - 1784, 1785, 1786, 1787, 1788, 1789, 1768, 1769, 1770, 1790, - 1771, 1772, 1773, 1774, 1775, 1776, 1791, 1792, 1793, 1777, - 1778, 1794, 1779, 1780, 1781, 1782, 1783, 1795, 1796, 1797, - 1798, 1784, 1785, 1786, 1787, 1788, 1789, 1799, 1800, 1801, - 1790, 1802, 1803, 1804, 1805, 1806, 1807, 1791, 1792, 1793, - 1808, 1809, 1794, 1810, 1811, 1812, 1813, 1814, 1795, 1796, - 1797, 1798, 1815, 1816, 1817, 1818, 1819, 1820, 1799, 1800, - 1801, 1821, 1802, 1803, 1804, 1805, 1806, 1807, 1822, 1823, - 1824, 1808, 1809, 1825, 1810, 1811, 1812, 1813, 1814, 1826, - - 1827, 1828, 1829, 1815, 1816, 1817, 1818, 1819, 1820, 1830, - 1832, 1833, 1821, 1831, 1834, 1835, 1836, 1837, 1838, 1822, - 1823, 1824, 1839, 362, 1825, 1840, 362, 1841, 1842, 1843, - 1826, 1827, 1828, 1829, 1844, 1845, 1846, 1847, 1848, 1849, - 1830, 1832, 1833, 1850, 1831, 1834, 1835, 1836, 1837, 1838, - 1851, 1852, 1853, 1839, 1854, 1855, 1840, 1856, 1841, 1842, - 1843, 1857, 1858, 1859, 1860, 1844, 1845, 1846, 1847, 1848, - 1849, 1861, 1862, 1863, 1850, 1864, 1865, 1866, 1867, 1868, - 1869, 1851, 1852, 1853, 1870, 1854, 1855, 1871, 1856, 1872, - 1873, 1874, 1857, 1858, 1859, 1860, 1875, 1876, 1877, 1878, - - 1879, 1880, 1861, 1862, 1863, 1881, 1864, 1865, 1866, 1867, - 1868, 1869, 1882, 1883, 1884, 1870, 1885, 1887, 1871, 1888, - 1872, 1873, 1874, 1891, 1889, 1892, 1890, 1875, 1876, 1877, - 1878, 1879, 1880, 1886, 362, 1893, 1881, 1894, 1895, 1896, - 1897, 1898, 1899, 1882, 1883, 1884, 362, 1885, 1887, 1900, - 1888, 1901, 1902, 1903, 1891, 1889, 1892, 1890, 1904, 1905, - 1906, 1907, 1908, 1909, 1886, 1910, 1893, 1911, 1894, 1895, - 1896, 1897, 1898, 1899, 1912, 1913, 1914, 1915, 1916, 1917, - 1900, 1918, 1901, 1902, 1903, 1919, 1920, 1921, 1922, 1904, - 1905, 1906, 1907, 1908, 1909, 1923, 1910, 1924, 1911, 1925, - - 1926, 1927, 1928, 1930, 1931, 1912, 1913, 1914, 1915, 1916, - 1917, 1929, 1918, 1932, 362, 1933, 1919, 1920, 1921, 1922, - 1934, 1935, 362, 1936, 1937, 1938, 1923, 1939, 1924, 1940, - 1925, 1926, 1927, 1928, 1930, 1931, 1941, 1942, 1943, 1944, - 1945, 1946, 1929, 1947, 1932, 1948, 1933, 1949, 1950, 1951, - 1952, 1934, 1935, 1953, 1936, 1937, 1938, 1954, 1939, 1955, - 1940, 1956, 1957, 1958, 362, 1959, 1960, 1941, 1942, 1943, - 1944, 1945, 1946, 1961, 1947, 1962, 1948, 1963, 1949, 1950, - 1951, 1952, 1964, 1965, 1953, 1966, 362, 1967, 1954, 1968, - 1955, 1969, 1956, 1957, 1958, 1970, 1959, 1960, 1971, 1972, - - 1973, 1974, 1976, 1977, 1961, 1978, 1962, 1979, 1963, 1980, - 1981, 1982, 1983, 1964, 1965, 1984, 1966, 1986, 1967, 1987, - 1968, 1988, 1969, 1989, 1990, 362, 1970, 1991, 1992, 1971, - 1972, 1973, 1974, 1976, 1977, 1993, 1978, 1994, 1979, 1995, - 1980, 1981, 1982, 1983, 1996, 1997, 1984, 1998, 1986, 1999, - 1987, 2000, 1988, 2001, 1989, 1990, 2002, 2003, 1991, 1992, - 2004, 2004, 2004, 2004, 2004, 2004, 1993, 2004, 1994, 2004, - 1995, 2004, 2004, 2004, 2004, 1996, 1997, 2004, 1998, 2004, - 1999, 2004, 2000, 2004, 2001, 2004, 2004, 2002, 2003, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 125, 125, - - 125, 125, 125, 125, 125, 125, 125, 129, 129, 129, - 129, 129, 129, 129, 129, 129, 134, 2004, 134, 134, - 134, 134, 134, 134, 134, 135, 2004, 135, 135, 135, - 135, 135, 135, 135, 139, 139, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 252, 252, 252, 252, 252, - 252, 252, 252, 252, 254, 2004, 254, 254, 254, 254, - 254, 254, 254, 274, 2004, 274, 358, 358, 358, 358, - 358, 358, 358, 358, 358, 363, 363, 363, 363, 363, - 363, 363, 363, 363, 367, 367, 367, 367, 367, 367, - 367, 367, 367, 369, 369, 369, 369, 369, 369, 369, - - 369, 369, 370, 370, 370, 2004, 2004, 370, 370, 2004, - 370, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 556, 2004, 2004, 556, 556, 2004, 556, 584, 584, 584, - 2004, 584, 584, 584, 584, 584, 586, 586, 586, 586, - 2004, 586, 586, 586, 586, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 13, 2004, 2004, 2004, 2004, 2004, + 235, 217, 223, 236, 224, 344, 351, 225, 226, 173, + + 237, 238, 227, 174, 283, 284, 228, 286, 356, 229, + 239, 230, 240, 287, 231, 285, 241, 357, 242, 133, + 243, 133, 133, 223, 133, 224, 133, 133, 225, 226, + 173, 136, 238, 227, 174, 283, 284, 228, 286, 356, + 229, 239, 230, 240, 287, 231, 285, 241, 357, 242, + 368, 243, 246, 247, 368, 155, 248, 156, 249, 329, + 250, 289, 290, 330, 279, 251, 297, 280, 187, 366, + 161, 292, 378, 378, 298, 293, 208, 349, 371, 139, + 372, 299, 300, 246, 247, 139, 155, 248, 156, 249, + 329, 250, 289, 290, 330, 279, 251, 297, 280, 187, + + 301, 161, 292, 306, 307, 298, 293, 208, 302, 371, + 139, 372, 299, 300, 303, 308, 139, 304, 314, 310, + 309, 328, 331, 311, 139, 325, 139, 321, 321, 312, + 333, 301, 313, 334, 306, 307, 318, 322, 332, 302, + 323, 341, 320, 320, 335, 303, 308, 380, 304, 314, + 310, 309, 324, 331, 311, 139, 342, 139, 336, 338, + 312, 333, 349, 313, 334, 317, 350, 339, 322, 332, + 345, 315, 341, 352, 316, 335, 340, 353, 380, 354, + 346, 348, 355, 324, 841, 347, 315, 342, 373, 336, + 338, 373, 385, 349, 359, 374, 374, 350, 339, 256, + + 390, 345, 315, 360, 352, 375, 255, 340, 353, 361, + 354, 346, 348, 355, 253, 145, 347, 138, 138, 362, + 140, 140, 393, 385, 396, 359, 399, 146, 400, 585, + 141, 390, 373, 136, 360, 2004, 375, 376, 377, 2004, + 361, 378, 378, 2004, 381, 381, 383, 383, 2004, 391, + 384, 384, 2004, 393, 382, 396, 2004, 399, 146, 400, + 392, 141, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 401, 402, 144, 386, + 391, 142, 142, 387, 142, 382, 394, 397, 407, 408, + 388, 392, 395, 404, 405, 406, 389, 403, 409, 411, + + 412, 398, 410, 413, 418, 384, 384, 401, 402, 421, + 386, 142, 142, 142, 387, 142, 2004, 394, 397, 407, + 408, 388, 414, 395, 404, 405, 406, 389, 403, 409, + 411, 412, 398, 410, 413, 418, 415, 416, 417, 424, + 421, 429, 142, 142, 142, 142, 142, 142, 142, 142, + 419, 422, 430, 414, 420, 423, 425, 431, 426, 427, + 432, 436, 428, 433, 437, 438, 439, 415, 416, 417, + 424, 434, 429, 2004, 444, 445, 2004, 435, 448, 456, + 457, 419, 422, 430, 2004, 420, 423, 425, 431, 426, + 427, 432, 436, 428, 433, 437, 438, 439, 440, 441, + + 446, 449, 434, 2004, 442, 444, 445, 447, 435, 448, + 456, 457, 464, 465, 466, 443, 453, 450, 462, 451, + 467, 454, 455, 468, 452, 458, 469, 459, 460, 440, + 441, 446, 449, 461, 463, 442, 472, 2004, 447, 474, + 473, 475, 476, 464, 465, 466, 443, 453, 450, 462, + 451, 467, 454, 455, 468, 452, 458, 469, 459, 460, + 470, 477, 478, 479, 461, 463, 480, 472, 471, 483, + 474, 473, 475, 476, 481, 484, 482, 485, 486, 489, + 491, 487, 492, 384, 384, 490, 500, 493, 488, 2004, + 501, 470, 477, 478, 479, 502, 2004, 480, 503, 471, + + 483, 504, 508, 509, 2004, 481, 484, 482, 485, 486, + 489, 491, 487, 492, 494, 495, 490, 500, 493, 488, + 496, 501, 505, 506, 497, 498, 502, 499, 510, 503, + 512, 513, 504, 508, 509, 507, 514, 515, 520, 517, + 524, 518, 525, 526, 527, 494, 495, 519, 516, 528, + 529, 496, 511, 505, 506, 497, 498, 521, 499, 510, + 530, 512, 513, 531, 532, 522, 507, 514, 515, 520, + 517, 524, 518, 525, 526, 527, 533, 523, 519, 516, + 528, 529, 534, 511, 535, 537, 538, 539, 521, 540, + 541, 530, 544, 545, 531, 532, 522, 546, 547, 542, + + 550, 548, 551, 552, 553, 554, 555, 533, 523, 275, + 275, 391, 2004, 534, 549, 535, 537, 538, 539, 558, + 540, 541, 543, 544, 545, 559, 561, 560, 546, 547, + 542, 550, 548, 551, 552, 553, 554, 555, 562, 387, + 414, 417, 391, 276, 419, 549, 388, 564, 563, 435, + 558, 566, 389, 543, 569, 570, 559, 561, 560, 425, + 454, 565, 427, 571, 464, 471, 572, 567, 573, 562, + 387, 414, 417, 442, 574, 419, 482, 388, 564, 563, + 435, 575, 566, 389, 568, 569, 570, 490, 498, 578, + 425, 454, 565, 427, 571, 464, 471, 572, 567, 573, + + 576, 579, 510, 580, 442, 574, 581, 482, 517, 520, + 577, 582, 575, 583, 2004, 568, 519, 516, 490, 498, + 578, 589, 589, 589, 589, 321, 321, 2004, 321, 321, + 2004, 576, 579, 510, 580, 322, 317, 581, 322, 517, + 520, 577, 582, 323, 583, 320, 320, 519, 516, 588, + 588, 590, 590, 589, 589, 324, 594, 595, 592, 592, + 596, 591, 593, 593, 597, 598, 322, 317, 599, 322, + 600, 602, 603, 604, 605, 606, 607, 610, 608, 611, + 612, 613, 614, 601, 615, 616, 324, 594, 595, 609, + 617, 596, 591, 620, 621, 597, 598, 622, 618, 599, + + 619, 600, 602, 603, 604, 605, 606, 607, 610, 608, + 611, 612, 613, 614, 601, 615, 616, 623, 624, 625, + 609, 617, 374, 374, 620, 621, 629, 2004, 622, 618, + 632, 619, 375, 376, 376, 633, 634, 628, 628, 635, + 362, 381, 381, 636, 637, 362, 362, 638, 623, 624, + 625, 382, 639, 640, 630, 630, 641, 629, 631, 631, + 642, 632, 643, 375, 644, 645, 633, 634, 646, 647, + 635, 648, 649, 650, 636, 637, 651, 652, 638, 656, + 653, 657, 382, 639, 640, 660, 661, 641, 654, 658, + 662, 642, 663, 643, 655, 644, 645, 664, 665, 646, + + 647, 666, 648, 649, 650, 667, 659, 651, 652, 668, + 656, 653, 657, 669, 670, 671, 660, 661, 672, 654, + 658, 662, 674, 663, 675, 655, 673, 676, 664, 665, + 679, 677, 666, 680, 681, 682, 667, 659, 683, 684, + 668, 678, 685, 686, 669, 670, 671, 687, 688, 672, + 689, 691, 692, 674, 690, 675, 693, 673, 676, 694, + 695, 679, 677, 696, 680, 681, 682, 697, 699, 683, + 684, 700, 678, 685, 686, 701, 702, 698, 687, 688, + 703, 689, 691, 692, 704, 690, 705, 693, 706, 707, + 694, 695, 708, 709, 696, 2004, 721, 2004, 697, 699, + + 2004, 724, 700, 725, 736, 2004, 701, 702, 698, 737, + 722, 703, 593, 593, 723, 704, 2004, 705, 738, 706, + 707, 739, 740, 708, 709, 710, 711, 721, 712, 741, + 713, 714, 724, 715, 725, 736, 716, 742, 743, 717, + 737, 722, 745, 718, 719, 723, 746, 720, 2004, 738, + 749, 2004, 739, 740, 2004, 750, 710, 711, 751, 712, + 741, 713, 714, 752, 715, 755, 2004, 716, 742, 743, + 717, 756, 747, 745, 718, 719, 748, 746, 720, 726, + 727, 749, 728, 753, 729, 730, 750, 731, 757, 751, + 732, 754, 761, 759, 752, 764, 755, 733, 734, 762, + + 765, 735, 756, 747, 760, 766, 763, 748, 767, 768, + 726, 727, 758, 728, 753, 729, 730, 769, 731, 757, + 770, 732, 754, 761, 759, 771, 764, 772, 733, 734, + 762, 765, 735, 773, 774, 760, 766, 763, 775, 767, + 768, 776, 777, 758, 779, 780, 781, 782, 769, 783, + 784, 770, 785, 786, 778, 787, 771, 788, 772, 789, + 790, 791, 792, 793, 773, 774, 794, 795, 796, 775, + 797, 802, 776, 777, 798, 779, 780, 781, 782, 799, + 783, 784, 800, 785, 786, 778, 787, 801, 788, 805, + 789, 790, 791, 792, 793, 803, 806, 794, 795, 796, + + 807, 797, 802, 808, 809, 798, 810, 804, 811, 812, + 799, 813, 814, 800, 815, 816, 817, 818, 801, 819, + 805, 820, 821, 822, 823, 824, 803, 806, 825, 826, + 654, 807, 827, 658, 808, 809, 828, 810, 804, 811, + 812, 673, 813, 814, 829, 815, 816, 817, 818, 830, + 819, 689, 820, 821, 822, 823, 824, 831, 697, 825, + 826, 654, 833, 827, 658, 723, 834, 828, 832, 747, + 835, 753, 673, 836, 759, 829, 777, 837, 838, 839, + 830, 840, 689, 799, 590, 590, 842, 842, 831, 697, + 843, 843, 844, 833, 591, 845, 723, 834, 846, 832, + + 747, 835, 753, 847, 836, 759, 848, 777, 837, 838, + 839, 849, 840, 850, 799, 593, 593, 851, 852, 853, + 854, 855, 856, 844, 857, 591, 845, 858, 859, 846, + 860, 861, 862, 863, 847, 864, 865, 848, 866, 867, + 868, 869, 849, 870, 850, 871, 876, 872, 851, 852, + 853, 854, 855, 856, 874, 857, 362, 877, 858, 859, + 873, 860, 861, 862, 863, 878, 864, 865, 879, 866, + 867, 868, 869, 362, 870, 880, 871, 876, 872, 628, + 628, 882, 362, 631, 631, 874, 631, 631, 877, 883, + 884, 873, 885, 886, 887, 888, 878, 889, 890, 879, + + 892, 893, 894, 895, 896, 898, 880, 899, 900, 901, + 903, 902, 882, 897, 904, 905, 906, 891, 907, 908, + 883, 884, 909, 885, 886, 887, 888, 910, 889, 890, + 911, 892, 893, 894, 895, 896, 898, 912, 899, 900, + 901, 903, 902, 913, 897, 904, 905, 906, 891, 907, + 908, 914, 915, 909, 916, 917, 918, 919, 910, 920, + 921, 911, 922, 923, 924, 925, 926, 927, 912, 928, + 929, 930, 931, 932, 913, 933, 934, 935, 936, 937, + 938, 939, 914, 915, 942, 916, 917, 918, 919, 943, + 920, 921, 940, 922, 923, 924, 925, 926, 927, 941, + + 928, 929, 930, 931, 932, 944, 933, 934, 935, 936, + 937, 938, 939, 945, 946, 942, 947, 948, 949, 951, + 943, 952, 953, 940, 954, 950, 955, 956, 957, 958, + 941, 959, 963, 960, 964, 965, 944, 966, 967, 961, + 968, 969, 970, 971, 945, 946, 972, 947, 948, 949, + 951, 962, 952, 953, 973, 954, 950, 955, 956, 957, + 958, 974, 959, 963, 960, 964, 965, 975, 966, 967, + 961, 968, 969, 970, 971, 976, 980, 972, 977, 981, + 982, 983, 962, 984, 978, 973, 985, 986, 989, 987, + 990, 991, 974, 988, 992, 993, 979, 994, 975, 995, + + 996, 997, 998, 999, 1000, 1001, 976, 980, 1002, 977, + 981, 982, 983, 1003, 984, 978, 1004, 985, 986, 989, + 987, 990, 991, 1007, 988, 992, 993, 979, 994, 1008, + 995, 996, 997, 998, 999, 1000, 1001, 1005, 1009, 1002, + 1010, 1011, 1006, 1012, 1003, 1013, 1014, 1004, 1015, 1016, + 1017, 1018, 1019, 1020, 1007, 1021, 1022, 1023, 1024, 1025, + 1008, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1005, 1009, + 1033, 1010, 1011, 1006, 1012, 1036, 1013, 1014, 1038, 1015, + 1016, 1017, 1018, 1019, 1020, 1037, 1021, 1022, 1023, 1024, + 1025, 1039, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1034, + + 1040, 1033, 1041, 1035, 1042, 1043, 1036, 1044, 1045, 1038, + 1046, 1047, 1048, 1049, 1050, 1051, 1037, 1052, 1053, 1054, + 1055, 1056, 1039, 1057, 1058, 1059, 1060, 1061, 1062, 1063, + 1034, 1040, 1064, 1041, 1035, 1042, 1043, 1065, 1044, 1045, + 1066, 1046, 1047, 1048, 1049, 1050, 1051, 1067, 1052, 1053, + 1054, 1055, 1056, 1068, 1057, 1058, 1059, 1060, 1061, 1062, + 1063, 1069, 1070, 1064, 1071, 1072, 940, 1073, 1065, 987, + 1074, 1066, 1075, 1076, 1077, 843, 843, 1078, 1067, 843, + 843, 1079, 1080, 1081, 1068, 1082, 1083, 1084, 1085, 1086, + 1087, 1088, 1069, 1070, 1089, 1071, 1072, 940, 1073, 1090, + + 987, 1074, 1091, 1075, 1076, 1077, 1092, 1093, 1078, 1094, + 1095, 1096, 1079, 1080, 1081, 1097, 1082, 1083, 1084, 1085, + 1086, 1087, 1088, 1098, 1099, 1089, 1100, 1101, 1102, 1103, + 1090, 362, 1105, 1091, 1104, 1106, 1107, 1092, 1093, 1108, + 1094, 1095, 1096, 1109, 1110, 1111, 1097, 1112, 362, 1113, + 1114, 1115, 1116, 1117, 1098, 1099, 1118, 1100, 1101, 1102, + 1103, 1119, 362, 1120, 1121, 1104, 1106, 1107, 1122, 1123, + 1108, 1126, 1127, 1128, 1109, 1110, 1111, 1129, 1112, 1130, + 1113, 1114, 1115, 1116, 1117, 1124, 1131, 1118, 1125, 1132, + 1133, 1134, 1119, 1135, 1120, 1121, 1136, 1137, 1138, 1122, + + 1123, 1139, 1126, 1127, 1128, 1140, 1141, 1142, 1129, 1143, + 1130, 1144, 1145, 1146, 1147, 1148, 1124, 1131, 1149, 1125, + 1132, 1133, 1134, 1150, 1135, 1157, 2004, 1136, 1137, 1138, + 2004, 1158, 1139, 362, 1309, 1159, 1140, 1141, 1142, 1162, + 1143, 1160, 1144, 1145, 1146, 1147, 1148, 1151, 1163, 1149, + 1164, 1161, 1165, 1166, 1150, 1172, 1157, 1152, 1173, 2004, + 1153, 1154, 1158, 1174, 1155, 1156, 1159, 1175, 1176, 1177, + 1162, 2004, 1160, 1178, 1179, 1180, 1181, 1182, 1151, 1163, + 1183, 1164, 1161, 1165, 1166, 1184, 1172, 1167, 1152, 1173, + 1168, 1153, 1154, 1169, 1174, 1155, 1156, 1170, 1175, 1176, + + 1177, 1185, 1171, 1186, 1178, 1179, 1180, 1181, 1182, 1187, + 1188, 1183, 1189, 1190, 1191, 1192, 1184, 1193, 1167, 1194, + 1195, 1168, 1196, 1197, 1169, 1198, 1199, 1200, 1170, 1201, + 1202, 1203, 1185, 1171, 1186, 1204, 1205, 1206, 1207, 1208, + 1187, 1188, 1209, 1189, 1190, 1191, 1192, 1210, 1193, 1211, + 1194, 1195, 1212, 1196, 1197, 1213, 1198, 1199, 1200, 1214, + 1201, 1202, 1203, 1215, 1216, 1217, 1204, 1205, 1206, 1207, + 1208, 1218, 1219, 1209, 1220, 1221, 1222, 1223, 1210, 1224, + 1211, 1225, 1226, 1212, 1227, 1230, 1213, 1231, 1228, 1232, + 1214, 1233, 1234, 1236, 1215, 1216, 1217, 1229, 1237, 1235, + + 1238, 1239, 1218, 1219, 1240, 1220, 1221, 1222, 1223, 1241, + 1224, 1242, 1225, 1226, 1243, 1227, 1230, 1247, 1231, 1228, + 1232, 1248, 1233, 1234, 1236, 1244, 1249, 1245, 1229, 1237, + 1235, 1238, 1239, 1250, 1251, 1240, 1252, 1253, 1254, 1255, + 1241, 1256, 1242, 1246, 1257, 1243, 1258, 1259, 1247, 1261, + 1262, 1263, 1248, 1260, 1265, 1266, 1244, 1249, 1245, 1267, + 1268, 1264, 1269, 1270, 1250, 1251, 1271, 1252, 1253, 1254, + 1255, 1272, 1256, 1273, 1246, 1257, 1274, 1258, 1259, 1275, + 1261, 1262, 1263, 1277, 1260, 1265, 1266, 1278, 1279, 1280, + 1267, 1268, 1264, 1269, 1270, 1281, 1276, 1271, 1282, 1283, + + 1138, 1119, 1272, 1120, 1273, 1151, 1161, 1274, 1169, 1284, + 1275, 1224, 1285, 1286, 1277, 1287, 1288, 1171, 1278, 1279, + 1280, 1289, 1290, 1291, 1292, 1293, 1281, 1276, 1294, 1282, + 1283, 1138, 1119, 1295, 1120, 1296, 1151, 1161, 1297, 1169, + 1284, 1298, 1224, 1285, 1286, 1299, 1287, 1288, 1171, 1300, + 1301, 1302, 1289, 1290, 1291, 1292, 1293, 1303, 1304, 1294, + 1305, 1306, 1307, 1308, 1295, 2004, 1296, 1312, 1313, 1297, + 1310, 1311, 1298, 1314, 1315, 1316, 1299, 1317, 1318, 1319, + 1300, 1301, 1302, 1320, 1321, 1322, 1323, 1324, 1303, 1304, + 1325, 1305, 1306, 1307, 1308, 362, 362, 1326, 1312, 1313, + + 1327, 1310, 1311, 1328, 1314, 1315, 1316, 1329, 1317, 1318, + 1319, 1330, 1331, 1332, 1320, 1321, 1322, 1323, 1324, 1333, + 1334, 1325, 1335, 1336, 1337, 1338, 1339, 1340, 1326, 1341, + 1342, 1327, 1343, 1344, 1328, 1345, 1346, 1347, 1329, 1348, + 1349, 1350, 1330, 1331, 1332, 1351, 1352, 1353, 1354, 1355, + 1333, 1334, 1356, 1335, 1336, 1337, 1338, 1339, 1340, 1357, + 1341, 1342, 1358, 1343, 1344, 1359, 1345, 1346, 1347, 1360, + 1348, 1349, 1350, 1361, 1363, 1364, 1351, 1352, 1353, 1354, + 1355, 1362, 1365, 1356, 1366, 1367, 1368, 1369, 1370, 1371, + 1357, 1372, 1373, 1358, 1374, 1375, 1359, 1376, 1377, 1378, + + 1360, 1379, 1380, 1381, 1361, 1363, 1364, 1382, 1383, 1384, + 1385, 1386, 1362, 1365, 1387, 1366, 1367, 1368, 1369, 1370, + 1371, 1388, 1372, 1373, 1389, 1374, 1375, 1390, 1376, 1377, + 1378, 1391, 1379, 1380, 1381, 1392, 1393, 1394, 1382, 1383, + 1384, 1385, 1386, 1395, 1396, 1387, 1397, 1399, 1400, 1401, + 1402, 1403, 1388, 1404, 1405, 1389, 1406, 1407, 1390, 1408, + 1409, 1410, 1391, 1411, 1412, 1413, 1392, 1393, 1394, 1414, + 1415, 1416, 1417, 1418, 1395, 1396, 1419, 1397, 1399, 1400, + 1401, 1402, 1403, 1420, 1404, 1405, 1421, 1406, 1407, 1422, + 1408, 1409, 1410, 1423, 1411, 1412, 1413, 1424, 1425, 1426, + + 1414, 1415, 1416, 1417, 1418, 1427, 1428, 1419, 1430, 1431, + 1432, 1433, 1434, 1435, 1420, 1436, 1437, 1421, 1438, 1439, + 1422, 1440, 1429, 1441, 1423, 1442, 1443, 1444, 1424, 1425, + 1426, 1445, 1446, 1447, 1448, 1449, 1427, 1428, 1450, 1430, + 1431, 1432, 1433, 1434, 1435, 1451, 1436, 1437, 1452, 1438, + 1439, 1453, 1440, 1429, 1441, 1454, 1442, 1443, 1444, 1455, + 1456, 1457, 1445, 1446, 1447, 1448, 1449, 1458, 1459, 1450, + 1460, 1461, 1462, 1463, 1464, 1465, 1451, 1466, 1467, 1452, + 1468, 1469, 1453, 1470, 1471, 1472, 1454, 1473, 1474, 1475, + 1455, 1456, 1457, 1477, 1479, 1476, 1480, 1481, 1458, 1459, + + 1482, 1460, 1461, 1462, 1463, 1464, 1465, 1483, 1466, 1467, + 1484, 1468, 1469, 1485, 1470, 1471, 1472, 362, 1473, 1474, + 1475, 362, 1486, 1487, 1477, 1479, 1476, 1480, 1481, 1488, + 1489, 1482, 1490, 1491, 1492, 1493, 1494, 1495, 1483, 1496, + 1497, 1484, 1498, 1499, 1485, 1500, 1501, 1502, 1503, 1504, + 1505, 1506, 1507, 1486, 1487, 1508, 1509, 1510, 1511, 1512, + 1488, 1489, 1513, 1490, 1491, 1492, 1493, 1494, 1495, 1514, + 1496, 1497, 1515, 1498, 1499, 1516, 1500, 1501, 1502, 1503, + 1504, 1505, 1506, 1507, 1517, 1518, 1508, 1509, 1510, 1511, + 1512, 1519, 1520, 1513, 1521, 1522, 1523, 1524, 1525, 1526, + + 1514, 1527, 1528, 1515, 1529, 1530, 1516, 1531, 1532, 1533, + 1534, 1535, 1536, 1537, 1538, 1517, 1518, 1539, 1540, 1541, + 1542, 1543, 1519, 1520, 1544, 1521, 1522, 1523, 1524, 1525, + 1526, 1545, 1527, 1528, 1546, 1529, 1530, 1547, 1531, 1532, + 1533, 1534, 1535, 1536, 1537, 1538, 1548, 1549, 1539, 1540, + 1541, 1542, 1543, 1550, 1551, 1544, 1552, 1553, 1556, 1554, + 1562, 1563, 1545, 1557, 1558, 1546, 1564, 1565, 1547, 1566, + 1567, 1568, 1569, 1570, 1559, 1571, 1560, 1548, 1549, 1555, + 1561, 1572, 1573, 1574, 1550, 1551, 1575, 1552, 1553, 1556, + 1554, 1562, 1563, 1576, 1557, 1558, 1577, 1564, 1565, 1578, + + 1566, 1567, 1568, 1569, 1570, 1559, 1571, 1560, 1579, 1580, + 1555, 1561, 1572, 1573, 1574, 1581, 1582, 1575, 1583, 1584, + 1585, 1586, 1587, 1588, 1576, 1589, 1590, 1577, 1591, 1592, + 1578, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1579, + 1580, 1601, 1602, 1603, 1604, 1605, 1581, 1582, 1606, 1583, + 1584, 1585, 1586, 1587, 1588, 1607, 1589, 1590, 1608, 1591, + 1592, 1609, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, + 1557, 1558, 1601, 1602, 1603, 1604, 1605, 1610, 1611, 1606, + 1612, 1613, 1614, 1560, 1615, 1616, 1607, 1561, 1617, 1608, + 1618, 1619, 1609, 1620, 1621, 1622, 1623, 1625, 1626, 1627, + + 1624, 1557, 1558, 1628, 1629, 1630, 1631, 1632, 1610, 1611, + 1633, 1612, 1613, 1614, 1560, 1615, 1616, 362, 1561, 1617, + 362, 1618, 1619, 1634, 1620, 1621, 1622, 1623, 1625, 1626, + 1627, 1624, 1635, 1636, 1628, 1629, 1630, 1631, 1632, 1637, + 1638, 1633, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, + 1647, 1648, 1649, 1650, 1634, 1651, 1652, 1653, 1654, 1655, + 1656, 1657, 1658, 1635, 1636, 1659, 1660, 1661, 1662, 1663, + 1637, 1638, 1664, 1639, 1640, 1641, 1642, 1643, 1644, 1645, + 1646, 1647, 1648, 1649, 1650, 1665, 1651, 1652, 1653, 1654, + 1655, 1656, 1657, 1658, 1666, 1667, 1659, 1660, 1661, 1662, + + 1663, 1668, 1669, 1664, 1670, 1671, 1672, 1673, 1674, 1675, + 1676, 1677, 1678, 1679, 1680, 1681, 1665, 1682, 1683, 1684, + 1685, 1686, 1687, 1688, 1689, 1666, 1667, 1690, 1691, 1692, + 1693, 1694, 1668, 1669, 1697, 1670, 1671, 1672, 1673, 1674, + 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1698, 1682, 1683, + 1684, 1685, 1686, 1687, 1688, 1689, 1695, 1700, 1690, 1691, + 1692, 1693, 1694, 1699, 1696, 1697, 1701, 1702, 1703, 1704, + 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1698, 1713, + 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1695, 1700, 1721, + 1722, 1723, 1724, 1725, 1699, 1696, 1726, 1701, 1702, 1703, + + 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1727, + 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1728, 1729, + 1721, 1722, 1723, 1724, 1725, 1730, 1731, 1726, 1732, 1733, + 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, + 1727, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1728, + 1729, 1752, 1753, 362, 362, 1754, 1730, 1731, 1755, 1732, + 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, + 1743, 1756, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, + 1757, 1758, 1752, 1753, 1759, 1760, 1754, 1761, 1762, 1755, + 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, + + 1773, 1774, 1756, 1775, 1776, 1777, 1778, 1779, 1780, 1781, + 1782, 1757, 1758, 1783, 1784, 1759, 1760, 1785, 1761, 1762, + 1786, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, + 1772, 1773, 1774, 1787, 1775, 1776, 1777, 1778, 1779, 1780, + 1781, 1782, 1788, 1789, 1783, 1784, 1790, 1791, 1785, 1792, + 1793, 1786, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, + 1802, 1803, 1804, 1805, 1787, 1806, 1807, 1808, 1809, 1810, + 1811, 1812, 1813, 1788, 1789, 1814, 1815, 1790, 1791, 1816, + 1792, 1793, 1817, 1794, 1795, 1796, 1797, 1798, 1799, 1800, + 1801, 1802, 1803, 1804, 1805, 1818, 1806, 1807, 1808, 1809, + + 1810, 1811, 1812, 1813, 1819, 1820, 1814, 1815, 1821, 1822, + 1816, 1823, 1824, 1817, 1825, 1826, 1827, 1828, 1829, 1831, + 1830, 1832, 1833, 1834, 1835, 1836, 1818, 1837, 1838, 362, + 1839, 1840, 1841, 1842, 1843, 1819, 1820, 362, 1844, 1821, + 1822, 1845, 1823, 1824, 1846, 1825, 1826, 1827, 1828, 1829, + 1831, 1830, 1832, 1833, 1834, 1835, 1836, 1847, 1837, 1838, + 1848, 1839, 1840, 1841, 1842, 1843, 1849, 1850, 1851, 1844, + 1852, 1853, 1845, 1854, 1855, 1846, 1856, 1857, 1858, 1859, + 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1847, 1868, + 1869, 1848, 1870, 1871, 1872, 1873, 1874, 1849, 1850, 1851, + + 1875, 1852, 1853, 1876, 1854, 1855, 1877, 1856, 1857, 1858, + 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1878, + 1868, 1869, 1879, 1870, 1871, 1872, 1873, 1874, 1880, 1881, + 1882, 1875, 1883, 1884, 1876, 1885, 1887, 1877, 1888, 1889, + 1891, 1892, 1890, 1893, 1894, 1895, 1896, 1897, 1898, 362, + 1878, 1899, 1886, 1879, 1900, 1901, 1902, 1903, 1904, 1880, + 1881, 1882, 362, 1883, 1884, 1905, 1885, 1887, 1906, 1888, + 1889, 1891, 1892, 1890, 1893, 1894, 1895, 1896, 1897, 1898, + 1907, 1908, 1899, 1886, 1909, 1900, 1901, 1902, 1903, 1904, + 1910, 1911, 1912, 1913, 1914, 1915, 1905, 1916, 1917, 1906, + + 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, + 1928, 1907, 1908, 1929, 1930, 1909, 362, 1931, 1932, 1933, + 1934, 1910, 1911, 1912, 1913, 1914, 1915, 1935, 1916, 1917, + 362, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, + 1927, 1928, 1936, 1937, 1929, 1930, 1938, 1939, 1931, 1932, + 1933, 1934, 1940, 1941, 1942, 1943, 1944, 1945, 1935, 1946, + 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, + 1958, 1959, 362, 1936, 1937, 1960, 1961, 1938, 1939, 1957, + 1962, 1963, 1964, 1940, 1941, 1942, 1943, 1944, 1945, 1965, + 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, + + 1956, 1958, 1959, 362, 1966, 1967, 1960, 1961, 1968, 1969, + 1957, 1962, 1963, 1964, 1970, 1971, 1972, 1973, 1974, 1976, + 1965, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1986, + 1987, 1988, 1989, 1990, 1991, 1966, 1967, 1992, 1993, 1968, + 1969, 1994, 362, 1995, 1996, 1970, 1971, 1972, 1973, 1974, + 1976, 1997, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, + 1986, 1987, 1988, 1989, 1990, 1991, 1998, 1999, 1992, 1993, + 2000, 2001, 1994, 2002, 1995, 1996, 2003, 2004, 2004, 2004, + 2004, 2004, 1997, 2004, 2004, 2004, 2004, 2004, 2004, 2004, + 2004, 2004, 2004, 2004, 2004, 2004, 2004, 1998, 1999, 2004, + + 2004, 2000, 2001, 2004, 2002, 2004, 2004, 2003, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 134, 2004, 134, 134, 134, + 134, 134, 134, 134, 135, 2004, 135, 135, 135, 135, + 135, 135, 135, 139, 139, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 252, 252, 252, 252, 252, 252, + 252, 252, 252, 254, 2004, 254, 254, 254, 254, 254, + 254, 254, 274, 2004, 274, 358, 358, 358, 358, 358, + 358, 358, 358, 358, 363, 363, 363, 363, 363, 363, + + 363, 363, 363, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 370, 370, 370, 2004, 2004, 370, 370, 2004, 370, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 556, + 2004, 2004, 556, 556, 2004, 556, 584, 584, 584, 2004, + 584, 584, 584, 584, 584, 586, 586, 586, 586, 2004, + 586, 586, 586, 586, 626, 626, 626, 626, 626, 626, + 626, 626, 626, 13, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, + 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, - 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, - 2004, 2004, 2004 + 2004, 2004 } ; -static yyconst flex_int16_t yy_chk[4644] = +static yyconst flex_int16_t yy_chk[4663] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1702,445 +1719,447 @@ static yyconst flex_int16_t yy_chk[4644] = 73, 35, 110, 73, 73, 36, 70, 64, 85, 36, 38, 38, 85, 39, 89, 43, 89, 39, 38, 43, 38, 39, 38, 43, 39, 38, 38, 39, 101, 43, - 39, 627, 43, 627, 78, 78, 255, 101, 254, 43, + 39, 627, 43, 627, 111, 115, 255, 101, 254, 43, 252, 38, 38, 142, 39, 89, 43, 89, 39, 38, 43, 38, 39, 38, 43, 39, 38, 38, 39, 136, - 43, 39, 42, 43, 42, 78, 78, 42, 42, 75, - - 43, 44, 42, 75, 74, 74, 42, 75, 111, 42, - 44, 42, 44, 75, 42, 74, 44, 115, 44, 135, - 44, 98, 98, 42, 126, 42, 126, 126, 42, 42, - 75, 98, 44, 42, 75, 74, 74, 42, 75, 111, - 42, 44, 42, 44, 75, 42, 74, 44, 115, 44, - 103, 44, 46, 46, 103, 72, 46, 72, 46, 104, - 46, 118, 98, 83, 72, 46, 128, 72, 80, 119, - 72, 83, 80, 83, 585, 104, 80, 127, 83, 83, - 123, 103, 80, 46, 46, 103, 72, 46, 72, 46, - 104, 46, 118, 130, 83, 72, 46, 84, 72, 80, - - 119, 72, 83, 80, 83, 84, 104, 80, 87, 83, - 83, 84, 87, 80, 84, 86, 86, 88, 87, 585, - 106, 87, 122, 88, 130, 88, 105, 86, 84, 105, - 378, 378, 86, 102, 106, 131, 84, 144, 99, 87, - 99, 99, 84, 87, 109, 84, 86, 86, 88, 87, - 99, 106, 87, 108, 88, 147, 88, 105, 86, 109, - 105, 108, 112, 86, 113, 106, 131, 114, 144, 116, - 108, 114, 112, 116, 113, 109, 117, 112, 149, 117, - 132, 99, 100, 132, 108, 133, 147, 133, 133, 96, - 109, 95, 108, 112, 151, 113, 94, 120, 114, 93, - - 116, 108, 114, 112, 116, 113, 120, 117, 112, 149, - 117, 153, 120, 137, 137, 138, 156, 138, 138, 140, - 140, 157, 120, 137, 132, 151, 158, 138, 120, 140, - 141, 141, 383, 383, 141, 141, 50, 120, 145, 145, - 146, 146, 153, 120, 146, 146, 49, 156, 145, 384, - 384, 48, 157, 152, 137, 19, 159, 158, 138, 152, - 140, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 150, 159, 143, 148, 145, - 143, 143, 148, 143, 152, 154, 150, 159, 162, 148, - 152, 160, 160, 160, 163, 148, 165, 166, 167, 154, - - 165, 168, 170, 170, 169, 171, 150, 159, 173, 148, - 143, 143, 143, 148, 143, 13, 154, 150, 169, 162, - 148, 175, 160, 160, 160, 163, 148, 165, 166, 167, - 154, 165, 168, 170, 170, 169, 171, 177, 178, 173, - 179, 143, 143, 143, 143, 143, 143, 143, 143, 169, - 172, 174, 175, 180, 172, 174, 176, 182, 176, 176, - 183, 184, 176, 185, 181, 588, 588, 187, 177, 178, - 188, 179, 181, 189, 190, 194, 196, 201, 181, 202, - 189, 172, 174, 0, 180, 172, 174, 176, 182, 176, - 176, 183, 184, 176, 185, 181, 186, 186, 187, 191, - - 199, 188, 186, 181, 189, 190, 194, 196, 201, 181, - 202, 189, 205, 186, 193, 191, 199, 191, 203, 193, - 193, 198, 191, 198, 198, 206, 203, 186, 186, 198, - 191, 199, 207, 186, 200, 200, 200, 204, 208, 209, - 210, 204, 200, 205, 186, 193, 191, 199, 191, 203, - 193, 193, 198, 191, 198, 198, 206, 203, 211, 212, - 198, 212, 213, 207, 214, 200, 200, 200, 204, 208, - 209, 210, 204, 200, 215, 216, 217, 218, 216, 219, - 589, 589, 217, 221, 219, 216, 0, 222, 223, 211, - 212, 0, 212, 213, 224, 214, 225, 592, 592, 227, - - 228, 230, 229, 231, 232, 215, 216, 217, 218, 216, - 219, 220, 220, 217, 221, 219, 216, 220, 222, 223, - 235, 220, 220, 237, 220, 224, 229, 225, 226, 226, - 227, 228, 230, 229, 231, 232, 233, 234, 236, 234, - 240, 226, 220, 220, 242, 234, 236, 233, 220, 243, - 244, 235, 220, 220, 237, 220, 245, 229, 236, 226, - 226, 246, 247, 248, 249, 250, 251, 233, 234, 236, - 234, 240, 226, 257, 258, 242, 234, 236, 233, 259, - 243, 244, 260, 261, 262, 263, 264, 245, 265, 236, - 266, 268, 246, 247, 248, 249, 250, 251, 267, 269, - - 270, 271, 272, 273, 257, 258, 278, 262, 279, 281, - 259, 267, 282, 260, 261, 262, 263, 264, 280, 265, - 280, 266, 268, 275, 275, 283, 0, 284, 277, 267, - 269, 270, 271, 272, 273, 277, 286, 278, 262, 279, - 281, 277, 267, 282, 285, 288, 289, 291, 285, 280, - 287, 280, 287, 287, 290, 292, 283, 275, 284, 277, - 290, 293, 294, 295, 296, 297, 277, 286, 299, 300, - 301, 290, 277, 302, 304, 285, 288, 289, 291, 285, - 303, 287, 305, 287, 287, 290, 292, 306, 307, 308, - 303, 290, 293, 294, 295, 296, 297, 309, 310, 299, - - 300, 301, 290, 312, 302, 304, 311, 313, 314, 310, - 329, 303, 0, 305, 311, 319, 319, 0, 306, 307, - 308, 303, 321, 321, 320, 319, 320, 320, 309, 310, - 330, 331, 321, 332, 312, 334, 320, 311, 313, 314, - 310, 329, 322, 322, 335, 311, 322, 322, 323, 323, - 324, 324, 333, 333, 324, 324, 319, 335, 323, 336, - 337, 330, 331, 321, 332, 338, 334, 320, 339, 340, - 341, 343, 344, 345, 346, 335, 348, 350, 351, 352, - 353, 355, 343, 333, 333, 354, 356, 354, 335, 323, - 336, 337, 357, 359, 360, 0, 338, 379, 361, 339, - - 340, 341, 343, 344, 345, 346, 385, 348, 350, 351, - 352, 353, 355, 343, 386, 387, 354, 356, 354, 361, - 388, 359, 360, 357, 359, 360, 374, 374, 379, 361, - 375, 375, 381, 381, 375, 375, 374, 385, 389, 382, - 382, 390, 381, 382, 382, 386, 387, 391, 392, 393, - 394, 388, 395, 396, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 408, 409, 411, 374, 0, 389, - 412, 406, 390, 381, 413, 414, 415, 406, 391, 392, - 393, 394, 410, 395, 396, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 408, 409, 411, 416, 410, - - 418, 412, 406, 419, 420, 413, 414, 415, 406, 421, - 422, 423, 424, 410, 425, 426, 427, 428, 429, 431, - 424, 432, 433, 434, 435, 436, 437, 428, 438, 416, - 410, 418, 439, 440, 419, 420, 441, 440, 442, 443, - 421, 422, 423, 424, 444, 425, 426, 427, 428, 429, - 431, 424, 432, 433, 434, 435, 436, 437, 428, 438, - 445, 446, 447, 439, 440, 448, 449, 441, 440, 442, - 443, 450, 447, 451, 452, 444, 453, 454, 455, 456, - 459, 460, 593, 593, 462, 0, 464, 628, 628, 465, - 0, 445, 446, 447, 463, 467, 448, 449, 463, 468, - - 630, 630, 450, 447, 451, 452, 469, 453, 454, 455, - 456, 459, 460, 461, 461, 462, 461, 464, 461, 461, - 465, 461, 470, 471, 461, 463, 467, 461, 472, 463, - 468, 461, 461, 473, 474, 461, 0, 469, 477, 0, - 478, 631, 631, 480, 461, 461, 481, 461, 482, 461, - 461, 483, 461, 470, 471, 461, 479, 485, 461, 472, - 479, 486, 461, 461, 473, 474, 461, 466, 466, 477, - 466, 478, 466, 466, 480, 466, 484, 481, 466, 482, - 489, 487, 483, 488, 484, 466, 466, 479, 485, 466, - 490, 479, 486, 491, 488, 492, 493, 490, 466, 466, - - 494, 466, 495, 466, 466, 487, 466, 484, 496, 466, - 497, 489, 487, 498, 488, 484, 466, 466, 499, 500, - 466, 490, 501, 502, 491, 488, 492, 493, 490, 503, - 504, 494, 505, 495, 506, 507, 487, 508, 509, 496, - 510, 497, 504, 511, 498, 513, 514, 515, 516, 499, - 500, 517, 518, 501, 502, 519, 520, 521, 522, 523, - 503, 504, 524, 505, 527, 506, 507, 525, 508, 509, - 526, 510, 525, 504, 511, 526, 513, 514, 515, 516, - 528, 529, 517, 518, 532, 535, 519, 520, 521, 522, - 523, 537, 528, 524, 538, 527, 539, 540, 525, 541, - - 542, 526, 543, 525, 544, 546, 526, 547, 548, 549, - 550, 528, 529, 551, 552, 532, 535, 553, 554, 558, - 559, 560, 537, 528, 561, 538, 562, 539, 540, 563, - 541, 542, 564, 543, 565, 544, 546, 566, 547, 548, - 549, 550, 567, 568, 551, 552, 569, 570, 553, 554, - 558, 559, 560, 571, 572, 561, 569, 562, 573, 574, - 563, 575, 576, 564, 577, 565, 578, 579, 566, 580, - 581, 582, 583, 567, 568, 591, 591, 569, 570, 591, - 591, 590, 590, 594, 571, 572, 595, 569, 596, 573, - 574, 590, 575, 576, 597, 577, 598, 578, 579, 599, - - 580, 581, 582, 583, 600, 601, 602, 603, 604, 605, - 606, 607, 608, 609, 594, 610, 611, 595, 612, 596, - 614, 615, 590, 616, 617, 597, 618, 598, 619, 620, - 599, 621, 622, 625, 0, 600, 601, 602, 603, 604, - 605, 606, 607, 608, 609, 624, 610, 611, 632, 612, - 633, 614, 615, 634, 616, 617, 623, 618, 624, 619, - 620, 625, 621, 622, 625, 623, 635, 636, 638, 639, - 640, 641, 642, 643, 644, 646, 624, 647, 648, 632, - 649, 633, 650, 651, 634, 652, 653, 623, 654, 655, - 656, 657, 656, 658, 652, 659, 647, 635, 636, 638, - - 639, 640, 641, 642, 643, 644, 646, 660, 647, 648, - 662, 649, 663, 650, 651, 664, 652, 653, 665, 654, - 655, 656, 657, 656, 658, 652, 659, 647, 666, 667, - 668, 669, 670, 672, 673, 674, 675, 676, 660, 677, - 678, 662, 680, 663, 681, 682, 664, 683, 684, 665, - 685, 686, 687, 688, 689, 690, 691, 692, 693, 666, - 667, 668, 669, 670, 672, 673, 674, 675, 676, 694, - 677, 678, 696, 680, 697, 681, 682, 699, 683, 684, - 700, 685, 686, 687, 688, 689, 690, 691, 692, 693, - 698, 701, 702, 703, 704, 706, 708, 698, 710, 707, - - 694, 711, 712, 696, 713, 697, 707, 714, 699, 715, - 716, 700, 717, 718, 719, 720, 721, 722, 723, 718, - 724, 698, 701, 702, 703, 704, 706, 708, 698, 710, - 707, 718, 711, 712, 725, 713, 726, 707, 714, 727, - 715, 716, 728, 717, 718, 719, 720, 721, 722, 723, - 718, 724, 729, 730, 731, 732, 734, 733, 735, 736, - 737, 738, 718, 733, 740, 725, 742, 726, 743, 744, - 727, 745, 743, 728, 746, 733, 747, 748, 749, 750, - 751, 752, 753, 729, 730, 731, 732, 734, 733, 735, - 736, 737, 738, 754, 733, 740, 755, 742, 756, 743, - - 744, 757, 745, 743, 758, 746, 733, 747, 748, 749, - 750, 751, 752, 753, 759, 760, 761, 762, 763, 764, - 760, 765, 766, 767, 754, 768, 769, 755, 770, 756, - 771, 772, 757, 773, 774, 758, 775, 776, 777, 778, - 779, 780, 781, 782, 783, 759, 760, 761, 762, 763, - 764, 760, 765, 766, 767, 784, 768, 769, 785, 770, - 786, 771, 772, 787, 773, 774, 792, 775, 776, 777, - 778, 779, 780, 781, 782, 783, 788, 790, 793, 794, - 788, 795, 796, 798, 799, 800, 784, 790, 801, 785, - 802, 786, 803, 804, 787, 805, 806, 792, 808, 809, - - 810, 811, 812, 813, 814, 815, 816, 788, 790, 793, - 794, 788, 795, 796, 798, 799, 800, 817, 790, 801, - 818, 802, 819, 803, 804, 820, 805, 806, 822, 808, - 809, 810, 811, 812, 813, 814, 815, 816, 823, 824, - 825, 826, 828, 830, 831, 832, 833, 834, 817, 835, - 836, 818, 838, 819, 839, 845, 820, 842, 842, 822, - 843, 843, 846, 847, 848, 849, 850, 851, 852, 823, - 824, 825, 826, 828, 830, 831, 832, 833, 834, 853, - 835, 836, 854, 838, 855, 839, 845, 856, 857, 858, - 859, 860, 861, 846, 847, 848, 849, 850, 851, 852, - - 862, 863, 864, 865, 866, 867, 868, 870, 871, 0, - 853, 874, 872, 854, 877, 855, 873, 873, 856, 857, - 858, 859, 860, 861, 874, 879, 880, 882, 883, 885, - 886, 862, 863, 864, 865, 866, 867, 868, 870, 871, - 872, 887, 874, 872, 888, 877, 889, 890, 892, 893, - 894, 893, 895, 896, 898, 899, 879, 880, 882, 883, - 885, 886, 897, 900, 901, 897, 902, 904, 905, 906, - 907, 910, 887, 912, 915, 888, 916, 889, 890, 892, - 893, 894, 893, 895, 896, 898, 899, 913, 913, 917, - 918, 919, 920, 897, 900, 901, 897, 902, 904, 905, - - 906, 907, 910, 922, 912, 915, 923, 916, 925, 926, - 929, 930, 932, 933, 931, 935, 936, 938, 913, 913, - 917, 918, 919, 920, 931, 939, 936, 931, 931, 940, - 941, 931, 931, 942, 922, 945, 947, 923, 948, 925, - 926, 929, 930, 932, 933, 931, 935, 936, 938, 0, - 949, 950, 951, 952, 953, 931, 939, 936, 931, 931, - 940, 941, 931, 931, 942, 943, 945, 947, 943, 948, - 954, 943, 955, 956, 957, 943, 958, 959, 960, 961, - 943, 949, 950, 951, 952, 953, 962, 963, 964, 965, - 966, 967, 969, 970, 971, 972, 943, 973, 974, 943, - - 975, 954, 943, 955, 956, 957, 943, 958, 959, 960, - 961, 943, 976, 977, 978, 979, 980, 962, 963, 964, - 965, 966, 967, 969, 970, 971, 972, 981, 973, 974, - 983, 975, 985, 986, 987, 988, 989, 990, 991, 992, - 993, 994, 995, 976, 977, 978, 979, 980, 996, 997, - 998, 999, 1000, 1001, 1002, 1003, 1004, 0, 981, 1006, - 1007, 983, 1008, 985, 986, 987, 988, 989, 990, 991, - 992, 993, 994, 995, 1009, 1011, 1012, 1013, 1014, 996, - 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1010, - 1006, 1007, 1015, 1008, 1016, 1017, 1010, 1005, 1018, 1021, - - 1022, 1021, 1023, 1024, 1025, 1009, 1011, 1012, 1013, 1014, - 1026, 1027, 1029, 1030, 1031, 1032, 1034, 1021, 1035, 1005, - 1010, 1037, 1039, 1015, 1041, 1016, 1017, 1010, 1005, 1018, - 1021, 1022, 1021, 1023, 1024, 1025, 1042, 1045, 1046, 1047, - 1048, 1026, 1027, 1029, 1030, 1031, 1032, 1034, 1021, 1035, - 1036, 1040, 1037, 1039, 1049, 1041, 1036, 1050, 1054, 1055, - 1056, 1040, 1059, 1060, 1061, 1062, 1063, 1042, 1045, 1046, - 1047, 1048, 1064, 1066, 1068, 1070, 1068, 1056, 1071, 1072, - 0, 1036, 1040, 1074, 1075, 1049, 1076, 1036, 1050, 1054, - 1055, 1056, 1040, 1059, 1060, 1061, 1062, 1063, 1077, 1078, - - 1079, 1080, 1073, 1064, 1066, 1068, 1070, 1068, 1056, 1071, - 1072, 1073, 1081, 1082, 1074, 1075, 1083, 1076, 1084, 1085, - 1086, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1096, 1077, - 1078, 1079, 1080, 1073, 1098, 1099, 1100, 1101, 1103, 1104, - 1104, 1107, 1073, 1081, 1082, 1105, 1106, 1083, 1108, 1084, - 1085, 1086, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1096, - 1109, 1110, 1111, 1112, 1114, 1098, 1099, 1100, 1101, 1103, - 1106, 1105, 1107, 1117, 1119, 1120, 1105, 1106, 1121, 1108, - 1122, 1123, 1125, 1127, 1128, 1129, 1130, 1131, 1132, 1134, - 1135, 1109, 1110, 1111, 1112, 1114, 1136, 1137, 1139, 1141, - - 1143, 1145, 1146, 1147, 1117, 1119, 1120, 1148, 1151, 1121, - 1152, 1122, 1123, 1125, 1127, 1128, 1129, 1130, 1131, 1132, - 1134, 1135, 1153, 1154, 1155, 1156, 1158, 1136, 1137, 1139, - 1141, 1143, 1145, 1146, 1147, 1159, 1160, 1161, 1148, 1151, - 1162, 1152, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1171, - 1170, 1174, 1175, 1153, 1154, 1155, 1156, 1158, 1170, 1176, - 1177, 1178, 1179, 1180, 1181, 1182, 1159, 1160, 1161, 1183, - 1184, 1162, 1185, 1163, 1164, 1165, 1166, 1167, 1168, 1169, - 1171, 1170, 1174, 1175, 1186, 1187, 1188, 1189, 1190, 1170, - 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1192, 1194, 1195, - - 1183, 1184, 1196, 1185, 1197, 1198, 1199, 1200, 1201, 1202, - 1203, 1204, 1205, 1206, 1207, 1186, 1187, 1188, 1189, 1190, - 1208, 1211, 1213, 1214, 1215, 1216, 1217, 1218, 1192, 1194, - 1195, 1219, 1220, 1196, 1225, 1197, 1198, 1199, 1200, 1201, - 1202, 1203, 1204, 1205, 1206, 1207, 1226, 1227, 1228, 1229, - 1230, 1208, 1211, 1213, 1214, 1215, 1216, 1217, 1218, 1231, - 1232, 1233, 1219, 1220, 1234, 1225, 1235, 1236, 1238, 1240, - 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1226, 1227, 1228, - 1229, 1230, 1249, 1252, 1255, 1256, 1257, 1258, 1259, 1260, - 1231, 1232, 1233, 1248, 1261, 1234, 1262, 1235, 1236, 1238, - - 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1263, 1248, - 1264, 1265, 1266, 1249, 1252, 1255, 1256, 1257, 1258, 1259, - 1260, 1267, 1268, 1269, 1248, 1261, 1270, 1262, 1273, 1275, - 1276, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1286, 1263, - 1248, 1264, 1265, 1266, 1289, 1290, 1291, 1292, 1293, 1294, - 1296, 1297, 1267, 1268, 1269, 1298, 1299, 1270, 1300, 1273, - 1275, 1276, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1286, - 1301, 1303, 1304, 1305, 1306, 1289, 1290, 1291, 1292, 1293, - 1294, 1296, 1297, 1307, 1309, 1310, 1298, 1299, 1312, 1300, - 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1323, - - 1324, 1301, 1303, 1304, 1305, 1306, 1325, 1326, 1328, 1310, - 1309, 1329, 1331, 1333, 1307, 1309, 1310, 1334, 1335, 1312, - 1337, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, - 1323, 1324, 1339, 1340, 1341, 1342, 1343, 1325, 1326, 1328, - 1344, 1345, 1329, 1331, 1333, 1346, 1347, 1348, 1334, 1335, - 1350, 1337, 1351, 1352, 1353, 1354, 1356, 1357, 1358, 1359, - 1360, 1361, 1362, 1339, 1340, 1341, 1342, 1343, 1363, 1364, - 1366, 1344, 1345, 1367, 1369, 1370, 1346, 1347, 1348, 1371, - 1372, 1350, 1373, 1351, 1352, 1353, 1354, 1356, 1357, 1358, - 1359, 1360, 1361, 1362, 1374, 1375, 1376, 1378, 1379, 1363, - - 1364, 1366, 1380, 1381, 1367, 1369, 1370, 1382, 1384, 1385, - 1371, 1372, 1386, 1373, 1387, 1388, 1389, 1390, 1392, 1393, - 1394, 1395, 1396, 1400, 1401, 1374, 1375, 1376, 1378, 1379, - 1398, 1402, 1398, 1380, 1381, 1404, 0, 1406, 1382, 1384, - 1385, 1407, 0, 1386, 1401, 1387, 1388, 1389, 1390, 1392, - 1393, 1394, 1395, 1396, 1400, 1401, 1403, 1403, 1409, 1411, - 1412, 1398, 1402, 1398, 1413, 1414, 1404, 1403, 1406, 1403, - 1415, 1416, 1407, 1403, 1417, 1401, 1418, 1419, 1420, 1421, - 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1403, 1403, 1409, - 1411, 1412, 1429, 1430, 1431, 1413, 1414, 1432, 1403, 1434, - - 1403, 1415, 1416, 1435, 1403, 1417, 1436, 1418, 1419, 1420, - 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1433, 1437, - 1433, 1439, 1440, 1429, 1430, 1431, 1441, 1442, 1432, 1443, - 1434, 1446, 1447, 1448, 1435, 1449, 1450, 1436, 1451, 1452, - 1453, 1454, 1455, 1456, 0, 0, 1458, 1460, 1462, 1433, - 1437, 1433, 1439, 1440, 1463, 1465, 1466, 1441, 1442, 1467, - 1443, 0, 1446, 1447, 1448, 1469, 1449, 1450, 1470, 1451, - 1452, 1453, 1454, 1455, 1456, 1457, 1457, 1458, 1460, 1462, - 1471, 1472, 1473, 1474, 1476, 1463, 1465, 1466, 1457, 1479, - 1467, 1480, 1457, 1477, 1481, 1482, 1469, 1483, 1485, 1470, - - 1486, 1487, 1488, 1489, 1490, 1491, 1457, 1457, 1476, 1492, - 1477, 1471, 1472, 1473, 1474, 1476, 1493, 1494, 1495, 1457, - 1479, 1497, 1480, 1457, 1477, 1481, 1482, 1498, 1483, 1485, - 1499, 1486, 1487, 1488, 1489, 1490, 1491, 1500, 1501, 1502, - 1492, 1504, 1505, 1506, 1507, 1508, 1510, 1493, 1494, 1495, - 1511, 1512, 1497, 1513, 1515, 1516, 1517, 1518, 1498, 1519, - 1520, 1499, 1521, 1522, 1523, 1524, 1525, 1526, 1500, 1501, - 1502, 1527, 1504, 1505, 1506, 1507, 1508, 1510, 1528, 1529, - 1530, 1511, 1512, 1531, 1513, 1515, 1516, 1517, 1518, 1532, - 1519, 1520, 1533, 1521, 1522, 1523, 1524, 1525, 1526, 1534, - - 1535, 1539, 1527, 1540, 1541, 1542, 1543, 1544, 1545, 1528, - 1529, 1530, 1546, 1547, 1531, 1550, 1551, 1552, 1553, 1554, - 1532, 1555, 1556, 1533, 1557, 1558, 1560, 1563, 1564, 1561, - 1534, 1535, 1539, 1559, 1540, 1541, 1542, 1543, 1544, 1545, - 1566, 1559, 1567, 1546, 1547, 1561, 1550, 1551, 1552, 1553, - 1554, 1569, 1555, 1556, 1570, 1557, 1558, 1560, 1563, 1564, - 1561, 1571, 1573, 1574, 1559, 1575, 1576, 1578, 1580, 1581, - 1583, 1566, 1559, 1567, 1584, 1585, 1561, 1586, 1587, 1588, - 1589, 1590, 1569, 1592, 1594, 1570, 1595, 1596, 1600, 1601, - 1602, 1603, 1571, 1573, 1574, 1604, 1575, 1576, 1578, 1580, - - 1581, 1583, 1606, 1607, 1609, 1584, 1585, 1612, 1586, 1587, - 1588, 1589, 1590, 1616, 1592, 1594, 1617, 1595, 1596, 1600, - 1601, 1602, 1603, 1618, 1620, 1621, 1604, 1625, 1623, 1624, - 1626, 1628, 1630, 1606, 1607, 1609, 1632, 1634, 1612, 1635, - 1637, 1638, 1640, 1641, 1616, 1623, 1624, 1617, 1643, 1644, - 1645, 1647, 1650, 1652, 1618, 1620, 1621, 1655, 1625, 1623, - 1624, 1626, 1628, 1630, 1656, 1657, 1658, 1632, 1634, 1659, - 1635, 1637, 1638, 1640, 1641, 1661, 1662, 1663, 1664, 1643, - 1644, 1645, 1647, 1650, 1652, 1665, 1666, 1667, 1655, 1668, - 1669, 1670, 1671, 1673, 1674, 1656, 1657, 1658, 1675, 1676, - - 1659, 1677, 1678, 1679, 1680, 1681, 1661, 1662, 1663, 1664, - 1683, 1684, 1685, 1686, 1687, 1688, 1665, 1666, 1667, 1689, - 1668, 1669, 1670, 1671, 1673, 1674, 1690, 1691, 1692, 1675, - 1676, 1693, 1677, 1678, 1679, 1680, 1681, 1694, 1695, 1696, - 1697, 1683, 1684, 1685, 1686, 1687, 1688, 1698, 1699, 1700, - 1689, 1701, 1702, 1703, 1704, 1705, 1706, 1690, 1691, 1692, - 1709, 1710, 1693, 1711, 1712, 1713, 1714, 1715, 1694, 1695, - 1696, 1697, 1719, 1721, 1723, 1725, 1726, 1727, 1698, 1699, - 1700, 1728, 1701, 1702, 1703, 1704, 1705, 1706, 1730, 1732, - 1733, 1709, 1710, 1734, 1711, 1712, 1713, 1714, 1715, 1735, - - 1736, 1737, 1738, 1719, 1721, 1723, 1725, 1726, 1727, 1740, - 1742, 1744, 1728, 1741, 1745, 1749, 1750, 1751, 1754, 1730, - 1732, 1733, 1755, 1741, 1734, 1757, 1740, 1759, 1763, 1764, - 1735, 1736, 1737, 1738, 1765, 1766, 1767, 1768, 1771, 1772, - 1740, 1742, 1744, 1773, 1741, 1745, 1749, 1750, 1751, 1754, - 1774, 1775, 1776, 1755, 1777, 1778, 1757, 1780, 1759, 1763, - 1764, 1781, 1782, 1783, 1784, 1765, 1766, 1767, 1768, 1771, - 1772, 1785, 1786, 1787, 1773, 1788, 1790, 1791, 1792, 1793, - 1794, 1774, 1775, 1776, 1795, 1777, 1778, 1796, 1780, 1797, - 1798, 1799, 1781, 1782, 1783, 1784, 1800, 1801, 1802, 1804, - - 1807, 1809, 1785, 1786, 1787, 1813, 1788, 1790, 1791, 1792, - 1793, 1794, 1815, 1816, 1817, 1795, 1818, 1820, 1796, 1824, - 1797, 1798, 1799, 1833, 1830, 1834, 1831, 1800, 1801, 1802, - 1804, 1807, 1809, 1818, 1830, 1835, 1813, 1837, 1838, 1839, - 1840, 1841, 1843, 1815, 1816, 1817, 1831, 1818, 1820, 1844, - 1824, 1845, 1846, 1847, 1833, 1830, 1834, 1831, 1852, 1853, - 1854, 1857, 1860, 1861, 1818, 1863, 1835, 1865, 1837, 1838, - 1839, 1840, 1841, 1843, 1866, 1867, 1868, 1869, 1870, 1871, - 1844, 1872, 1845, 1846, 1847, 1873, 1875, 1878, 1880, 1852, - 1853, 1854, 1857, 1860, 1861, 1882, 1863, 1883, 1865, 1884, - - 1885, 1887, 1889, 1891, 1893, 1866, 1867, 1868, 1869, 1870, - 1871, 1890, 1872, 1894, 1890, 1896, 1873, 1875, 1878, 1880, - 1898, 1899, 1889, 1900, 1901, 1903, 1882, 1904, 1883, 1905, - 1884, 1885, 1887, 1889, 1891, 1893, 1907, 1908, 1910, 1911, - 1915, 1917, 1890, 1918, 1894, 1919, 1896, 1920, 1921, 1922, - 1923, 1898, 1899, 1924, 1900, 1901, 1903, 1925, 1904, 1927, - 1905, 1928, 1929, 1930, 1928, 1931, 1935, 1907, 1908, 1910, - 1911, 1915, 1917, 1936, 1918, 1938, 1919, 1939, 1920, 1921, - 1922, 1923, 1941, 1945, 1924, 1946, 1929, 1947, 1925, 1948, - 1927, 1950, 1928, 1929, 1930, 1951, 1931, 1935, 1952, 1953, - - 1954, 1956, 1958, 1960, 1936, 1961, 1938, 1962, 1939, 1963, - 1965, 1968, 1971, 1941, 1945, 1972, 1946, 1977, 1947, 1978, - 1948, 1981, 1950, 1982, 1983, 1956, 1951, 1986, 1987, 1952, - 1953, 1954, 1956, 1958, 1960, 1988, 1961, 1989, 1962, 1991, - 1963, 1965, 1968, 1971, 1992, 1993, 1972, 1994, 1977, 1997, - 1978, 1998, 1981, 1999, 1982, 1983, 2001, 2002, 1986, 1987, - 0, 0, 0, 0, 0, 0, 1988, 0, 1989, 0, - 1991, 0, 0, 0, 0, 1992, 1993, 0, 1994, 0, - 1997, 0, 1998, 0, 1999, 0, 0, 2001, 2002, 2005, - 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2006, 2006, - - 2006, 2006, 2006, 2006, 2006, 2006, 2006, 2007, 2007, 2007, - 2007, 2007, 2007, 2007, 2007, 2007, 2008, 0, 2008, 2008, - 2008, 2008, 2008, 2008, 2008, 2009, 0, 2009, 2009, 2009, - 2009, 2009, 2009, 2009, 2010, 2010, 2011, 2011, 2011, 2011, - 2011, 2011, 2011, 2011, 2011, 2012, 2012, 2012, 2012, 2012, - 2012, 2012, 2012, 2012, 2013, 0, 2013, 2013, 2013, 2013, - 2013, 2013, 2013, 2014, 0, 2014, 2015, 2015, 2015, 2015, - 2015, 2015, 2015, 2015, 2015, 2016, 2016, 2016, 2016, 2016, - 2016, 2016, 2016, 2016, 2017, 2017, 2017, 2017, 2017, 2017, - 2017, 2017, 2017, 2018, 2018, 2018, 2018, 2018, 2018, 2018, - - 2018, 2018, 2019, 2019, 2019, 0, 0, 2019, 2019, 0, - 2019, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, - 2021, 0, 0, 2021, 2021, 0, 2021, 2022, 2022, 2022, - 0, 2022, 2022, 2022, 2022, 2022, 2023, 2023, 2023, 2023, - 0, 2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024, 2024, - 2024, 2024, 2024, 2024, 2004, 2004, 2004, 2004, 2004, 2004, + 43, 39, 42, 43, 42, 111, 115, 42, 42, 75, + + 43, 44, 42, 75, 74, 74, 42, 75, 118, 42, + 44, 42, 44, 75, 42, 74, 44, 119, 44, 126, + 44, 126, 126, 42, 133, 42, 133, 133, 42, 42, + 75, 135, 44, 42, 75, 74, 74, 42, 75, 118, + 42, 44, 42, 44, 75, 42, 74, 44, 119, 44, + 128, 44, 46, 46, 127, 72, 46, 72, 46, 103, + 46, 78, 78, 103, 72, 46, 83, 72, 78, 123, + 72, 80, 378, 378, 83, 80, 83, 122, 130, 80, + 131, 83, 83, 46, 46, 80, 72, 46, 72, 46, + 103, 46, 78, 78, 103, 72, 46, 83, 72, 78, + + 84, 72, 80, 86, 86, 83, 80, 83, 84, 130, + 80, 131, 83, 83, 84, 86, 80, 84, 88, 87, + 86, 102, 104, 87, 88, 100, 88, 98, 98, 87, + 105, 84, 87, 105, 86, 86, 96, 98, 104, 84, + 99, 109, 99, 99, 106, 84, 86, 144, 84, 88, + 87, 86, 99, 104, 87, 88, 109, 88, 106, 108, + 87, 105, 114, 87, 105, 95, 114, 108, 98, 104, + 112, 113, 109, 116, 94, 106, 108, 116, 144, 117, + 112, 113, 117, 99, 585, 112, 93, 109, 132, 106, + 108, 132, 147, 114, 120, 137, 137, 114, 108, 50, + + 149, 112, 113, 120, 116, 137, 49, 108, 116, 120, + 117, 112, 113, 117, 48, 138, 112, 138, 138, 120, + 140, 140, 151, 147, 153, 120, 156, 138, 157, 585, + 140, 149, 132, 19, 120, 13, 137, 141, 141, 0, + 120, 141, 141, 0, 145, 145, 146, 146, 0, 150, + 146, 146, 0, 151, 145, 153, 0, 156, 138, 157, + 150, 140, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 158, 159, 143, 148, + 150, 143, 143, 148, 143, 145, 152, 154, 162, 163, + 148, 150, 152, 160, 160, 160, 148, 159, 165, 166, + + 167, 154, 165, 168, 171, 383, 383, 158, 159, 173, + 148, 143, 143, 143, 148, 143, 0, 152, 154, 162, + 163, 148, 169, 152, 160, 160, 160, 148, 159, 165, + 166, 167, 154, 165, 168, 171, 169, 170, 170, 175, + 173, 177, 143, 143, 143, 143, 143, 143, 143, 143, + 172, 174, 178, 169, 172, 174, 176, 179, 176, 176, + 180, 182, 176, 181, 183, 184, 185, 169, 170, 170, + 175, 181, 177, 0, 187, 188, 0, 181, 190, 194, + 196, 172, 174, 178, 0, 172, 174, 176, 179, 176, + 176, 180, 182, 176, 181, 183, 184, 185, 186, 186, + + 189, 191, 181, 0, 186, 187, 188, 189, 181, 190, + 194, 196, 200, 200, 200, 186, 193, 191, 199, 191, + 200, 193, 193, 201, 191, 198, 202, 198, 198, 186, + 186, 189, 191, 198, 199, 186, 204, 0, 189, 205, + 204, 206, 207, 200, 200, 200, 186, 193, 191, 199, + 191, 200, 193, 193, 201, 191, 198, 202, 198, 198, + 203, 208, 209, 210, 198, 199, 211, 204, 203, 213, + 205, 204, 206, 207, 212, 214, 212, 215, 216, 217, + 218, 216, 219, 384, 384, 217, 221, 219, 216, 0, + 222, 203, 208, 209, 210, 223, 0, 211, 224, 203, + + 213, 225, 227, 228, 0, 212, 214, 212, 215, 216, + 217, 218, 216, 219, 220, 220, 217, 221, 219, 216, + 220, 222, 226, 226, 220, 220, 223, 220, 229, 224, + 230, 231, 225, 227, 228, 226, 232, 233, 235, 234, + 237, 234, 240, 242, 243, 220, 220, 234, 233, 244, + 245, 220, 229, 226, 226, 220, 220, 236, 220, 229, + 246, 230, 231, 247, 248, 236, 226, 232, 233, 235, + 234, 237, 234, 240, 242, 243, 249, 236, 234, 233, + 244, 245, 250, 229, 251, 257, 258, 259, 236, 260, + 261, 246, 263, 264, 247, 248, 236, 265, 266, 262, + + 268, 267, 269, 270, 271, 272, 273, 249, 236, 275, + 275, 278, 0, 250, 267, 251, 257, 258, 259, 279, + 260, 261, 262, 263, 264, 280, 281, 280, 265, 266, + 262, 268, 267, 269, 270, 271, 272, 273, 282, 277, + 283, 284, 278, 275, 285, 267, 277, 286, 285, 288, + 279, 289, 277, 262, 291, 292, 280, 281, 280, 287, + 293, 287, 287, 294, 295, 296, 297, 290, 299, 282, + 277, 283, 284, 290, 300, 285, 301, 277, 286, 285, + 288, 302, 289, 277, 290, 291, 292, 304, 305, 306, + 287, 293, 287, 287, 294, 295, 296, 297, 290, 299, + + 303, 307, 308, 309, 290, 300, 310, 301, 311, 312, + 303, 313, 302, 314, 0, 290, 311, 310, 304, 305, + 306, 588, 588, 589, 589, 319, 319, 0, 321, 321, + 0, 303, 307, 308, 309, 319, 329, 310, 321, 311, + 312, 303, 313, 320, 314, 320, 320, 311, 310, 322, + 322, 323, 323, 322, 322, 320, 330, 331, 324, 324, + 332, 323, 324, 324, 333, 333, 319, 329, 334, 321, + 335, 336, 337, 338, 339, 340, 341, 344, 343, 345, + 346, 348, 350, 335, 351, 352, 320, 330, 331, 343, + 353, 332, 323, 355, 356, 333, 333, 357, 354, 334, + + 354, 335, 336, 337, 338, 339, 340, 341, 344, 343, + 345, 346, 348, 350, 335, 351, 352, 359, 360, 361, + 343, 353, 374, 374, 355, 356, 379, 0, 357, 354, + 385, 354, 374, 375, 375, 386, 387, 375, 375, 388, + 361, 381, 381, 389, 390, 359, 360, 391, 359, 360, + 361, 381, 392, 393, 382, 382, 394, 379, 382, 382, + 395, 385, 396, 374, 397, 398, 386, 387, 399, 400, + 388, 401, 402, 403, 389, 390, 404, 405, 391, 408, + 406, 409, 381, 392, 393, 411, 412, 394, 406, 410, + 413, 395, 414, 396, 406, 397, 398, 415, 416, 399, + + 400, 418, 401, 402, 403, 419, 410, 404, 405, 420, + 408, 406, 409, 421, 422, 423, 411, 412, 424, 406, + 410, 413, 425, 414, 426, 406, 424, 427, 415, 416, + 429, 428, 418, 431, 432, 433, 419, 410, 434, 435, + 420, 428, 436, 437, 421, 422, 423, 438, 439, 424, + 440, 441, 442, 425, 440, 426, 443, 424, 427, 444, + 445, 429, 428, 446, 431, 432, 433, 447, 448, 434, + 435, 449, 428, 436, 437, 450, 451, 447, 438, 439, + 452, 440, 441, 442, 453, 440, 454, 443, 455, 456, + 444, 445, 459, 460, 446, 0, 462, 0, 447, 448, + + 0, 464, 449, 465, 467, 0, 450, 451, 447, 468, + 463, 452, 592, 592, 463, 453, 0, 454, 469, 455, + 456, 470, 471, 459, 460, 461, 461, 462, 461, 472, + 461, 461, 464, 461, 465, 467, 461, 473, 474, 461, + 468, 463, 477, 461, 461, 463, 478, 461, 0, 469, + 480, 0, 470, 471, 0, 481, 461, 461, 482, 461, + 472, 461, 461, 483, 461, 485, 0, 461, 473, 474, + 461, 486, 479, 477, 461, 461, 479, 478, 461, 466, + 466, 480, 466, 484, 466, 466, 481, 466, 487, 482, + 466, 484, 489, 488, 483, 491, 485, 466, 466, 490, + + 492, 466, 486, 479, 488, 493, 490, 479, 494, 495, + 466, 466, 487, 466, 484, 466, 466, 496, 466, 487, + 497, 466, 484, 489, 488, 498, 491, 499, 466, 466, + 490, 492, 466, 500, 501, 488, 493, 490, 502, 494, + 495, 503, 504, 487, 505, 506, 507, 508, 496, 509, + 510, 497, 511, 513, 504, 514, 498, 515, 499, 516, + 517, 518, 519, 520, 500, 501, 521, 522, 523, 502, + 524, 527, 503, 504, 525, 505, 506, 507, 508, 525, + 509, 510, 526, 511, 513, 504, 514, 526, 515, 529, + 516, 517, 518, 519, 520, 528, 532, 521, 522, 523, + + 535, 524, 527, 537, 538, 525, 539, 528, 540, 541, + 525, 542, 543, 526, 544, 546, 547, 548, 526, 549, + 529, 550, 551, 552, 553, 554, 528, 532, 558, 559, + 560, 535, 561, 562, 537, 538, 563, 539, 528, 540, + 541, 564, 542, 543, 565, 544, 546, 547, 548, 566, + 549, 567, 550, 551, 552, 553, 554, 568, 569, 558, + 559, 560, 570, 561, 562, 571, 572, 563, 569, 573, + 574, 575, 564, 576, 577, 565, 578, 579, 580, 581, + 566, 582, 567, 583, 590, 590, 591, 591, 568, 569, + 591, 591, 594, 570, 590, 595, 571, 572, 596, 569, + + 573, 574, 575, 597, 576, 577, 598, 578, 579, 580, + 581, 599, 582, 600, 583, 593, 593, 601, 602, 603, + 604, 605, 606, 594, 607, 590, 595, 608, 609, 596, + 610, 611, 612, 614, 597, 615, 616, 598, 617, 618, + 619, 620, 599, 621, 600, 622, 632, 623, 601, 602, + 603, 604, 605, 606, 625, 607, 623, 633, 608, 609, + 624, 610, 611, 612, 614, 634, 615, 616, 635, 617, + 618, 619, 620, 624, 621, 636, 622, 632, 623, 628, + 628, 638, 625, 630, 630, 625, 631, 631, 633, 639, + 640, 624, 641, 642, 643, 644, 634, 646, 647, 635, + + 648, 649, 650, 651, 652, 653, 636, 654, 655, 656, + 657, 656, 638, 652, 658, 659, 660, 647, 662, 663, + 639, 640, 664, 641, 642, 643, 644, 665, 646, 647, + 666, 648, 649, 650, 651, 652, 653, 667, 654, 655, + 656, 657, 656, 668, 652, 658, 659, 660, 647, 662, + 663, 669, 670, 664, 672, 673, 674, 675, 665, 676, + 677, 666, 678, 680, 681, 682, 683, 684, 667, 685, + 686, 687, 688, 689, 668, 690, 691, 692, 693, 694, + 696, 697, 669, 670, 699, 672, 673, 674, 675, 700, + 676, 677, 698, 678, 680, 681, 682, 683, 684, 698, + + 685, 686, 687, 688, 689, 701, 690, 691, 692, 693, + 694, 696, 697, 702, 703, 699, 704, 706, 707, 708, + 700, 710, 711, 698, 712, 707, 713, 714, 715, 716, + 698, 717, 719, 718, 720, 721, 701, 722, 723, 718, + 724, 725, 726, 727, 702, 703, 728, 704, 706, 707, + 708, 718, 710, 711, 729, 712, 707, 713, 714, 715, + 716, 730, 717, 719, 718, 720, 721, 731, 722, 723, + 718, 724, 725, 726, 727, 732, 734, 728, 733, 735, + 736, 737, 718, 738, 733, 729, 740, 742, 744, 743, + 745, 746, 730, 743, 747, 748, 733, 749, 731, 750, + + 751, 752, 753, 754, 755, 756, 732, 734, 757, 733, + 735, 736, 737, 758, 738, 733, 759, 740, 742, 744, + 743, 745, 746, 761, 743, 747, 748, 733, 749, 762, + 750, 751, 752, 753, 754, 755, 756, 760, 763, 757, + 764, 765, 760, 766, 758, 767, 768, 759, 769, 770, + 771, 772, 773, 774, 761, 775, 776, 777, 778, 779, + 762, 780, 781, 782, 783, 784, 785, 786, 760, 763, + 787, 764, 765, 760, 766, 790, 767, 768, 792, 769, + 770, 771, 772, 773, 774, 790, 775, 776, 777, 778, + 779, 793, 780, 781, 782, 783, 784, 785, 786, 788, + + 794, 787, 795, 788, 796, 798, 790, 799, 800, 792, + 801, 802, 803, 804, 805, 806, 790, 808, 809, 810, + 811, 812, 793, 813, 814, 815, 816, 817, 818, 819, + 788, 794, 820, 795, 788, 796, 798, 822, 799, 800, + 823, 801, 802, 803, 804, 805, 806, 824, 808, 809, + 810, 811, 812, 825, 813, 814, 815, 816, 817, 818, + 819, 826, 828, 820, 830, 831, 832, 833, 822, 834, + 835, 823, 836, 838, 839, 842, 842, 845, 824, 843, + 843, 846, 847, 848, 825, 849, 850, 851, 852, 853, + 854, 855, 826, 828, 856, 830, 831, 832, 833, 857, + + 834, 835, 858, 836, 838, 839, 859, 860, 845, 861, + 862, 863, 846, 847, 848, 864, 849, 850, 851, 852, + 853, 854, 855, 865, 866, 856, 867, 868, 870, 871, + 857, 873, 873, 858, 872, 874, 877, 859, 860, 879, + 861, 862, 863, 880, 882, 883, 864, 885, 874, 886, + 887, 888, 889, 890, 865, 866, 892, 867, 868, 870, + 871, 893, 872, 893, 894, 872, 874, 877, 895, 896, + 879, 898, 899, 900, 880, 882, 883, 901, 885, 902, + 886, 887, 888, 889, 890, 897, 904, 892, 897, 905, + 906, 907, 893, 910, 893, 894, 912, 913, 913, 895, + + 896, 915, 898, 899, 900, 916, 917, 918, 901, 919, + 902, 920, 922, 923, 925, 926, 897, 904, 929, 897, + 905, 906, 907, 930, 910, 932, 0, 912, 913, 913, + 0, 933, 915, 1104, 1104, 935, 916, 917, 918, 938, + 919, 936, 920, 922, 923, 925, 926, 931, 939, 929, + 940, 936, 941, 942, 930, 945, 932, 931, 947, 0, + 931, 931, 933, 948, 931, 931, 935, 949, 950, 951, + 938, 0, 936, 952, 953, 954, 955, 956, 931, 939, + 957, 940, 936, 941, 942, 958, 945, 943, 931, 947, + 943, 931, 931, 943, 948, 931, 931, 943, 949, 950, + + 951, 959, 943, 960, 952, 953, 954, 955, 956, 961, + 962, 957, 963, 964, 965, 966, 958, 967, 943, 969, + 970, 943, 971, 972, 943, 973, 974, 975, 943, 976, + 977, 978, 959, 943, 960, 979, 980, 981, 983, 985, + 961, 962, 986, 963, 964, 965, 966, 987, 967, 988, + 969, 970, 989, 971, 972, 990, 973, 974, 975, 991, + 976, 977, 978, 992, 993, 994, 979, 980, 981, 983, + 985, 995, 996, 986, 997, 998, 999, 1000, 987, 1001, + 988, 1002, 1003, 989, 1004, 1006, 990, 1007, 1005, 1008, + 991, 1009, 1010, 1011, 992, 993, 994, 1005, 1012, 1010, + + 1013, 1014, 995, 996, 1015, 997, 998, 999, 1000, 1016, + 1001, 1017, 1002, 1003, 1018, 1004, 1006, 1022, 1007, 1005, + 1008, 1023, 1009, 1010, 1011, 1021, 1024, 1021, 1005, 1012, + 1010, 1013, 1014, 1025, 1026, 1015, 1027, 1029, 1030, 1031, + 1016, 1032, 1017, 1021, 1034, 1018, 1035, 1036, 1022, 1037, + 1039, 1040, 1023, 1036, 1041, 1042, 1021, 1024, 1021, 1045, + 1046, 1040, 1047, 1048, 1025, 1026, 1049, 1027, 1029, 1030, + 1031, 1050, 1032, 1054, 1021, 1034, 1055, 1035, 1036, 1056, + 1037, 1039, 1040, 1059, 1036, 1041, 1042, 1060, 1061, 1062, + 1045, 1046, 1040, 1047, 1048, 1063, 1056, 1049, 1064, 1066, + + 1070, 1068, 1050, 1068, 1054, 1071, 1072, 1055, 1073, 1074, + 1056, 1075, 1076, 1077, 1059, 1078, 1079, 1073, 1060, 1061, + 1062, 1080, 1081, 1082, 1083, 1084, 1063, 1056, 1085, 1064, + 1066, 1070, 1068, 1086, 1068, 1088, 1071, 1072, 1089, 1073, + 1074, 1090, 1075, 1076, 1077, 1091, 1078, 1079, 1073, 1092, + 1093, 1094, 1080, 1081, 1082, 1083, 1084, 1096, 1098, 1085, + 1099, 1100, 1101, 1103, 1086, 0, 1088, 1107, 1108, 1089, + 1105, 1106, 1090, 1109, 1110, 1111, 1091, 1112, 1114, 1117, + 1092, 1093, 1094, 1119, 1120, 1121, 1122, 1123, 1096, 1098, + 1125, 1099, 1100, 1101, 1103, 1106, 1105, 1127, 1107, 1108, + + 1128, 1105, 1106, 1129, 1109, 1110, 1111, 1130, 1112, 1114, + 1117, 1131, 1132, 1134, 1119, 1120, 1121, 1122, 1123, 1135, + 1136, 1125, 1137, 1139, 1141, 1143, 1145, 1146, 1127, 1147, + 1148, 1128, 1151, 1152, 1129, 1153, 1154, 1155, 1130, 1156, + 1158, 1159, 1131, 1132, 1134, 1160, 1161, 1162, 1163, 1164, + 1135, 1136, 1165, 1137, 1139, 1141, 1143, 1145, 1146, 1166, + 1147, 1148, 1167, 1151, 1152, 1168, 1153, 1154, 1155, 1169, + 1156, 1158, 1159, 1170, 1171, 1174, 1160, 1161, 1162, 1163, + 1164, 1170, 1175, 1165, 1176, 1177, 1178, 1179, 1180, 1181, + 1166, 1182, 1183, 1167, 1184, 1185, 1168, 1186, 1187, 1188, + + 1169, 1189, 1190, 1192, 1170, 1171, 1174, 1194, 1195, 1196, + 1197, 1198, 1170, 1175, 1199, 1176, 1177, 1178, 1179, 1180, + 1181, 1200, 1182, 1183, 1201, 1184, 1185, 1202, 1186, 1187, + 1188, 1203, 1189, 1190, 1192, 1204, 1205, 1206, 1194, 1195, + 1196, 1197, 1198, 1207, 1208, 1199, 1211, 1213, 1214, 1215, + 1216, 1217, 1200, 1218, 1219, 1201, 1220, 1225, 1202, 1226, + 1227, 1228, 1203, 1229, 1230, 1231, 1204, 1205, 1206, 1232, + 1233, 1234, 1235, 1236, 1207, 1208, 1238, 1211, 1213, 1214, + 1215, 1216, 1217, 1240, 1218, 1219, 1241, 1220, 1225, 1242, + 1226, 1227, 1228, 1243, 1229, 1230, 1231, 1244, 1245, 1246, + + 1232, 1233, 1234, 1235, 1236, 1247, 1248, 1238, 1249, 1252, + 1255, 1256, 1257, 1258, 1240, 1259, 1260, 1241, 1261, 1262, + 1242, 1263, 1248, 1264, 1243, 1265, 1266, 1267, 1244, 1245, + 1246, 1268, 1269, 1270, 1273, 1275, 1247, 1248, 1276, 1249, + 1252, 1255, 1256, 1257, 1258, 1278, 1259, 1260, 1279, 1261, + 1262, 1280, 1263, 1248, 1264, 1281, 1265, 1266, 1267, 1282, + 1283, 1284, 1268, 1269, 1270, 1273, 1275, 1286, 1289, 1276, + 1290, 1291, 1292, 1293, 1294, 1296, 1278, 1297, 1298, 1279, + 1299, 1300, 1280, 1301, 1303, 1304, 1281, 1305, 1306, 1307, + 1282, 1283, 1284, 1310, 1312, 1309, 1313, 1314, 1286, 1289, + + 1315, 1290, 1291, 1292, 1293, 1294, 1296, 1316, 1297, 1298, + 1317, 1299, 1300, 1318, 1301, 1303, 1304, 1310, 1305, 1306, + 1307, 1309, 1319, 1320, 1310, 1312, 1309, 1313, 1314, 1321, + 1323, 1315, 1324, 1325, 1326, 1328, 1329, 1331, 1316, 1333, + 1334, 1317, 1335, 1337, 1318, 1339, 1340, 1341, 1342, 1343, + 1344, 1345, 1346, 1319, 1320, 1347, 1348, 1350, 1351, 1352, + 1321, 1323, 1353, 1324, 1325, 1326, 1328, 1329, 1331, 1354, + 1333, 1334, 1356, 1335, 1337, 1357, 1339, 1340, 1341, 1342, + 1343, 1344, 1345, 1346, 1358, 1359, 1347, 1348, 1350, 1351, + 1352, 1360, 1361, 1353, 1362, 1363, 1364, 1366, 1367, 1369, + + 1354, 1370, 1371, 1356, 1372, 1373, 1357, 1374, 1375, 1376, + 1378, 1379, 1380, 1381, 1382, 1358, 1359, 1384, 1385, 1386, + 1387, 1388, 1360, 1361, 1389, 1362, 1363, 1364, 1366, 1367, + 1369, 1390, 1370, 1371, 1392, 1372, 1373, 1393, 1374, 1375, + 1376, 1378, 1379, 1380, 1381, 1382, 1394, 1395, 1384, 1385, + 1386, 1387, 1388, 1396, 1398, 1389, 1398, 1400, 1402, 1401, + 1404, 1406, 1390, 1403, 1403, 1392, 1407, 1409, 1393, 1411, + 1412, 1413, 1414, 1415, 1403, 1416, 1403, 1394, 1395, 1401, + 1403, 1417, 1418, 1419, 1396, 1398, 1420, 1398, 1400, 1402, + 1401, 1404, 1406, 1421, 1403, 1403, 1422, 1407, 1409, 1423, + + 1411, 1412, 1413, 1414, 1415, 1403, 1416, 1403, 1424, 1425, + 1401, 1403, 1417, 1418, 1419, 1426, 1427, 1420, 1428, 1429, + 1430, 1431, 1432, 1433, 1421, 1433, 1434, 1422, 1435, 1436, + 1423, 1437, 1439, 1440, 1441, 1442, 1443, 1446, 1447, 1424, + 1425, 1448, 1449, 1450, 1451, 1452, 1426, 1427, 1453, 1428, + 1429, 1430, 1431, 1432, 1433, 1454, 1433, 1434, 1455, 1435, + 1436, 1456, 1437, 1439, 1440, 1441, 1442, 1443, 1446, 1447, + 1457, 1457, 1448, 1449, 1450, 1451, 1452, 1458, 1460, 1453, + 1462, 1463, 1465, 1457, 1466, 1467, 1454, 1457, 1469, 1455, + 1470, 1471, 1456, 1472, 1473, 1474, 1476, 1479, 1480, 1481, + + 1477, 1457, 1457, 1482, 1483, 1485, 1486, 1487, 1458, 1460, + 1488, 1462, 1463, 1465, 1457, 1466, 1467, 1477, 1457, 1469, + 1476, 1470, 1471, 1489, 1472, 1473, 1474, 1476, 1479, 1480, + 1481, 1477, 1490, 1491, 1482, 1483, 1485, 1486, 1487, 1492, + 1493, 1488, 1494, 1495, 1497, 1498, 1499, 1500, 1501, 1502, + 1504, 1505, 1506, 1507, 1489, 1508, 1510, 1511, 1512, 1513, + 1515, 1516, 1517, 1490, 1491, 1518, 1519, 1520, 1521, 1522, + 1492, 1493, 1523, 1494, 1495, 1497, 1498, 1499, 1500, 1501, + 1502, 1504, 1505, 1506, 1507, 1524, 1508, 1510, 1511, 1512, + 1513, 1515, 1516, 1517, 1525, 1526, 1518, 1519, 1520, 1521, + + 1522, 1527, 1528, 1523, 1529, 1530, 1531, 1532, 1533, 1534, + 1535, 1539, 1540, 1541, 1542, 1543, 1524, 1544, 1545, 1546, + 1547, 1550, 1551, 1552, 1553, 1525, 1526, 1554, 1555, 1556, + 1557, 1558, 1527, 1528, 1560, 1529, 1530, 1531, 1532, 1533, + 1534, 1535, 1539, 1540, 1541, 1542, 1543, 1561, 1544, 1545, + 1546, 1547, 1550, 1551, 1552, 1553, 1559, 1563, 1554, 1555, + 1556, 1557, 1558, 1561, 1559, 1560, 1564, 1566, 1567, 1569, + 1570, 1571, 1573, 1574, 1575, 1576, 1578, 1580, 1561, 1581, + 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1559, 1563, 1590, + 1592, 1594, 1595, 1596, 1561, 1559, 1600, 1564, 1566, 1567, + + 1569, 1570, 1571, 1573, 1574, 1575, 1576, 1578, 1580, 1601, + 1581, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1602, 1603, + 1590, 1592, 1594, 1595, 1596, 1604, 1606, 1600, 1607, 1609, + 1612, 1616, 1617, 1618, 1620, 1621, 1623, 1624, 1625, 1626, + 1601, 1628, 1630, 1632, 1634, 1635, 1637, 1638, 1640, 1602, + 1603, 1641, 1643, 1623, 1624, 1644, 1604, 1606, 1645, 1607, + 1609, 1612, 1616, 1617, 1618, 1620, 1621, 1623, 1624, 1625, + 1626, 1647, 1628, 1630, 1632, 1634, 1635, 1637, 1638, 1640, + 1650, 1652, 1641, 1643, 1655, 1656, 1644, 1657, 1658, 1645, + 1659, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, + + 1670, 1671, 1647, 1673, 1674, 1675, 1676, 1677, 1678, 1679, + 1680, 1650, 1652, 1681, 1683, 1655, 1656, 1684, 1657, 1658, + 1685, 1659, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, + 1669, 1670, 1671, 1686, 1673, 1674, 1675, 1676, 1677, 1678, + 1679, 1680, 1687, 1688, 1681, 1683, 1689, 1690, 1684, 1691, + 1692, 1685, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, + 1701, 1702, 1703, 1704, 1686, 1705, 1706, 1709, 1710, 1711, + 1712, 1713, 1714, 1687, 1688, 1715, 1719, 1689, 1690, 1721, + 1691, 1692, 1723, 1693, 1694, 1695, 1696, 1697, 1698, 1699, + 1700, 1701, 1702, 1703, 1704, 1725, 1705, 1706, 1709, 1710, + + 1711, 1712, 1713, 1714, 1726, 1727, 1715, 1719, 1728, 1730, + 1721, 1732, 1733, 1723, 1734, 1735, 1736, 1737, 1738, 1741, + 1740, 1742, 1744, 1745, 1749, 1750, 1725, 1751, 1754, 1741, + 1755, 1757, 1759, 1763, 1764, 1726, 1727, 1740, 1765, 1728, + 1730, 1766, 1732, 1733, 1767, 1734, 1735, 1736, 1737, 1738, + 1741, 1740, 1742, 1744, 1745, 1749, 1750, 1768, 1751, 1754, + 1771, 1755, 1757, 1759, 1763, 1764, 1772, 1773, 1774, 1765, + 1775, 1776, 1766, 1777, 1778, 1767, 1780, 1781, 1782, 1783, + 1784, 1785, 1786, 1787, 1788, 1790, 1791, 1792, 1768, 1793, + 1794, 1771, 1795, 1796, 1797, 1798, 1799, 1772, 1773, 1774, + + 1800, 1775, 1776, 1801, 1777, 1778, 1802, 1780, 1781, 1782, + 1783, 1784, 1785, 1786, 1787, 1788, 1790, 1791, 1792, 1804, + 1793, 1794, 1807, 1795, 1796, 1797, 1798, 1799, 1809, 1813, + 1815, 1800, 1816, 1817, 1801, 1818, 1820, 1802, 1824, 1830, + 1833, 1834, 1831, 1835, 1837, 1838, 1839, 1840, 1841, 1830, + 1804, 1843, 1818, 1807, 1844, 1845, 1846, 1847, 1852, 1809, + 1813, 1815, 1831, 1816, 1817, 1853, 1818, 1820, 1854, 1824, + 1830, 1833, 1834, 1831, 1835, 1837, 1838, 1839, 1840, 1841, + 1857, 1860, 1843, 1818, 1861, 1844, 1845, 1846, 1847, 1852, + 1863, 1865, 1866, 1867, 1868, 1869, 1853, 1870, 1871, 1854, + + 1872, 1873, 1875, 1878, 1880, 1882, 1883, 1884, 1885, 1887, + 1889, 1857, 1860, 1890, 1891, 1861, 1890, 1893, 1894, 1896, + 1898, 1863, 1865, 1866, 1867, 1868, 1869, 1899, 1870, 1871, + 1889, 1872, 1873, 1875, 1878, 1880, 1882, 1883, 1884, 1885, + 1887, 1889, 1900, 1901, 1890, 1891, 1903, 1904, 1893, 1894, + 1896, 1898, 1905, 1907, 1908, 1910, 1911, 1915, 1899, 1917, + 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1927, 1928, + 1930, 1931, 1928, 1900, 1901, 1935, 1936, 1903, 1904, 1929, + 1938, 1939, 1941, 1905, 1907, 1908, 1910, 1911, 1915, 1945, + 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1927, + + 1928, 1930, 1931, 1929, 1946, 1947, 1935, 1936, 1948, 1950, + 1929, 1938, 1939, 1941, 1951, 1952, 1953, 1954, 1956, 1958, + 1945, 1960, 1961, 1962, 1963, 1965, 1968, 1971, 1972, 1977, + 1978, 1981, 1982, 1983, 1986, 1946, 1947, 1987, 1988, 1948, + 1950, 1989, 1956, 1991, 1992, 1951, 1952, 1953, 1954, 1956, + 1958, 1993, 1960, 1961, 1962, 1963, 1965, 1968, 1971, 1972, + 1977, 1978, 1981, 1982, 1983, 1986, 1994, 1997, 1987, 1988, + 1998, 1999, 1989, 2001, 1991, 1992, 2002, 0, 0, 0, + 0, 0, 1993, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1994, 1997, 0, + + 0, 1998, 1999, 0, 2001, 0, 0, 2002, 2005, 2005, + 2005, 2005, 2005, 2005, 2005, 2005, 2005, 2006, 2006, 2006, + 2006, 2006, 2006, 2006, 2006, 2006, 2007, 2007, 2007, 2007, + 2007, 2007, 2007, 2007, 2007, 2008, 0, 2008, 2008, 2008, + 2008, 2008, 2008, 2008, 2009, 0, 2009, 2009, 2009, 2009, + 2009, 2009, 2009, 2010, 2010, 2011, 2011, 2011, 2011, 2011, + 2011, 2011, 2011, 2011, 2012, 2012, 2012, 2012, 2012, 2012, + 2012, 2012, 2012, 2013, 0, 2013, 2013, 2013, 2013, 2013, + 2013, 2013, 2014, 0, 2014, 2015, 2015, 2015, 2015, 2015, + 2015, 2015, 2015, 2015, 2016, 2016, 2016, 2016, 2016, 2016, + + 2016, 2016, 2016, 2017, 2017, 2017, 2017, 2017, 2017, 2017, + 2017, 2017, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, + 2018, 2019, 2019, 2019, 0, 0, 2019, 2019, 0, 2019, + 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2021, + 0, 0, 2021, 2021, 0, 2021, 2022, 2022, 2022, 0, + 2022, 2022, 2022, 2022, 2022, 2023, 2023, 2023, 2023, 0, + 2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024, 2024, 2024, + 2024, 2024, 2024, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, + 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, - 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, 2004, - 2004, 2004, 2004 + 2004, 2004 } ; static yy_state_type yy_last_accepting_state; @@ -2241,7 +2260,7 @@ char path[MS_MAXPATHLEN]; -#line 2245 "/Users/tbonfort/dev/mapserver/maplexer.c" +#line 2264 "/home/tbonfort/dev/mapserver/maplexer.c" #define INITIAL 0 #define URL_VARIABLE 1 @@ -2271,11 +2290,11 @@ void msyyset_extra (YY_EXTRA_TYPE user_defined ); FILE *msyyget_in (void ); -void msyyset_in (FILE * in_str ); +void msyyset_in (FILE * _in_str ); FILE *msyyget_out (void ); -void msyyset_out (FILE * out_str ); +void msyyset_out (FILE * _out_str ); yy_size_t msyyget_leng (void ); @@ -2283,7 +2302,7 @@ char *msyyget_text (void ); int msyyget_lineno (void ); -void msyyset_lineno (int line_number ); +void msyyset_lineno (int _line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. @@ -2297,8 +2316,12 @@ extern int msyywrap (void ); #endif #endif +#ifndef YY_NO_UNPUT + static void yyunput (int c,char *buf_ptr ); +#endif + #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif @@ -2319,7 +2342,12 @@ static int input (void ); /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else #define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ @@ -2327,7 +2355,7 @@ static int input (void ); /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ -#define ECHO fwrite( msyytext, msyyleng, 1, msyyout ) +#define ECHO do { if (fwrite( msyytext, msyyleng, 1, msyyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, @@ -2338,7 +2366,7 @@ static int input (void ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - yy_size_t n; \ + size_t n; \ for ( n = 0; n < max_size && \ (c = getc( msyyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -2406,7 +2434,7 @@ extern int msyylex (void); /* Code executed at the end of each rule. */ #ifndef YY_BREAK -#define YY_BREAK break; +#define YY_BREAK /*LINTED*/break; #endif #define YY_RULE_SETUP \ @@ -2416,10 +2444,37 @@ extern int msyylex (void); */ YY_DECL { - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! msyyin ) + msyyin = stdin; + + if ( ! msyyout ) + msyyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + msyyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + msyy_create_buffer(msyyin,YY_BUF_SIZE ); + } + + msyy_load_buffer_state( ); + } + + { #line 87 "maplexer.l" if (msyystring_buffer == NULL) @@ -2494,35 +2549,9 @@ YY_DECL break; } -#line 2498 "/Users/tbonfort/dev/mapserver/maplexer.c" - - if ( !(yy_init) ) - { - (yy_init) = 1; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! (yy_start) ) - (yy_start) = 1; /* first start state */ - - if ( ! msyyin ) - msyyin = stdin; - - if ( ! msyyout ) - msyyout = stdout; - - if ( ! YY_CURRENT_BUFFER ) { - msyyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - msyy_create_buffer(msyyin,YY_BUF_SIZE ); - } - - msyy_load_buffer_state( ); - } +#line 2553 "/home/tbonfort/dev/mapserver/maplexer.c" - while ( 1 ) /* loops until end-of-file is reached */ + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); @@ -2538,7 +2567,7 @@ YY_DECL yy_match: do { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; @@ -2553,7 +2582,7 @@ YY_DECL yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 4555 ); + while ( yy_base[yy_current_state] != 4574 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -4526,7 +4555,7 @@ YY_RULE_SETUP #line 744 "maplexer.l" ECHO; YY_BREAK -#line 4530 "/Users/tbonfort/dev/mapserver/maplexer.c" +#line 4559 "/home/tbonfort/dev/mapserver/maplexer.c" case YY_STATE_EOF(URL_VARIABLE): case YY_STATE_EOF(URL_STRING): case YY_STATE_EOF(EXPRESSION_STRING): @@ -4661,6 +4690,7 @@ case YY_STATE_EOF(MSSTRING): "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ + } /* end of user's declarations */ } /* end of msyylex */ /* yy_get_next_buffer - try to read in a new buffer @@ -4672,9 +4702,9 @@ case YY_STATE_EOF(MSSTRING): */ static int yy_get_next_buffer (void) { - register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - register char *source = (yytext_ptr); - register int number_to_move, i; + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = (yytext_ptr); + yy_size_t number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) @@ -4703,7 +4733,7 @@ static int yy_get_next_buffer (void) /* Try to read more data. */ /* First move last chars to start of buffer. */ - number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + number_to_move = (yy_size_t) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); @@ -4723,7 +4753,7 @@ static int yy_get_next_buffer (void) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); @@ -4785,9 +4815,9 @@ static int yy_get_next_buffer (void) else ret_val = EOB_ACT_CONTINUE_SCAN; - if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + if ((int) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ - yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) msyyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); @@ -4806,14 +4836,14 @@ static int yy_get_next_buffer (void) static yy_state_type yy_get_previous_state (void) { - register yy_state_type yy_current_state; - register char *yy_cp; + yy_state_type yy_current_state; + char *yy_cp; yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 88); + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 88); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; @@ -4838,10 +4868,10 @@ static int yy_get_next_buffer (void) */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { - register int yy_is_jam; - register char *yy_cp = (yy_c_buf_p); + int yy_is_jam; + char *yy_cp = (yy_c_buf_p); - register YY_CHAR yy_c = 88; + YY_CHAR yy_c = 88; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; @@ -4856,12 +4886,14 @@ static int yy_get_next_buffer (void) yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 2004); - return yy_is_jam ? 0 : yy_current_state; + return yy_is_jam ? 0 : yy_current_state; } - static void yyunput (int c, register char * yy_bp ) +#ifndef YY_NO_UNPUT + + static void yyunput (int c, char * yy_bp ) { - register char *yy_cp; + char *yy_cp; yy_cp = (yy_c_buf_p); @@ -4871,10 +4903,10 @@ static int yy_get_next_buffer (void) if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ - register yy_size_t number_to_move = (yy_n_chars) + 2; - register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + yy_size_t number_to_move = (yy_n_chars) + 2; + char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; - register char *source = + char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) @@ -4896,6 +4928,8 @@ static int yy_get_next_buffer (void) (yy_c_buf_p) = yy_cp; } +#endif + #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) @@ -4944,7 +4978,7 @@ static int yy_get_next_buffer (void) case EOB_ACT_END_OF_FILE: { if ( msyywrap( ) ) - return 0; + return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; @@ -5045,7 +5079,7 @@ static void msyy_load_buffer_state (void) if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in msyy_create_buffer()" ); - b->yy_buf_size = size; + b->yy_buf_size = (yy_size_t)size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. @@ -5080,10 +5114,6 @@ static void msyy_load_buffer_state (void) msyyfree((void *) b ); } -#ifndef __cplusplus -extern int isatty (int ); -#endif /* __cplusplus */ - /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a msyyrestart() or at EOF. @@ -5204,7 +5234,7 @@ static void msyyensure_buffer_stack (void) * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ - num_to_alloc = 1; + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ (yy_buffer_stack) = (struct yy_buffer_state**)msyyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); @@ -5221,7 +5251,7 @@ static void msyyensure_buffer_stack (void) if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ - int grow_size = 8 /* arbitrary grow size */; + yy_size_t grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)msyyrealloc @@ -5288,8 +5318,8 @@ YY_BUFFER_STATE msyy_scan_string (yyconst char * yystr ) /** Setup the input buffer state to scan the given bytes. The next call to msyylex() will * scan from a @e copy of @a bytes. - * @param bytes the byte buffer to scan - * @param len the number of bytes in the buffer pointed to by @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ @@ -5297,7 +5327,8 @@ YY_BUFFER_STATE msyy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_le { YY_BUFFER_STATE b; char *buf; - yy_size_t n, i; + yy_size_t n; + yy_size_t i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; @@ -5328,7 +5359,7 @@ YY_BUFFER_STATE msyy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_le static void yy_fatal_error (yyconst char* msg ) { - (void) fprintf( stderr, "%s\n", msg ); + (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } @@ -5394,29 +5425,29 @@ char *msyyget_text (void) } /** Set the current line number. - * @param line_number + * @param _line_number line number * */ -void msyyset_lineno (int line_number ) +void msyyset_lineno (int _line_number ) { - msyylineno = line_number; + msyylineno = _line_number; } /** Set the input stream. This does not discard the current * input buffer. - * @param in_str A readable stream. + * @param _in_str A readable stream. * * @see msyy_switch_to_buffer */ -void msyyset_in (FILE * in_str ) +void msyyset_in (FILE * _in_str ) { - msyyin = in_str ; + msyyin = _in_str ; } -void msyyset_out (FILE * out_str ) +void msyyset_out (FILE * _out_str ) { - msyyout = out_str ; + msyyout = _out_str ; } int msyyget_debug (void) @@ -5424,9 +5455,9 @@ int msyyget_debug (void) return msyy_flex_debug; } -void msyyset_debug (int bdebug ) +void msyyset_debug (int _bdebug ) { - msyy_flex_debug = bdebug ; + msyy_flex_debug = _bdebug ; } static int yy_init_globals (void) @@ -5486,7 +5517,8 @@ int msyylex_destroy (void) #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { - register int i; + + int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } @@ -5495,7 +5527,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { - register int n; + int n; for ( n = 0; s[n]; ++n ) ; @@ -5505,11 +5537,12 @@ static int yy_flex_strlen (yyconst char * s ) void *msyyalloc (yy_size_t size ) { - return (void *) malloc( size ); + return (void *) malloc( size ); } void *msyyrealloc (void * ptr, yy_size_t size ) { + /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter @@ -5522,7 +5555,7 @@ void *msyyrealloc (void * ptr, yy_size_t size ) void msyyfree (void * ptr ) { - free( (char *) ptr ); /* see msyyrealloc() for (char *) cast */ + free( (char *) ptr ); /* see msyyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" diff --git a/maplexer.l b/maplexer.l index ba7d7407c6..0a89173ab3 100644 --- a/maplexer.l +++ b/maplexer.l @@ -354,7 +354,7 @@ char path[MS_MAXPATHLEN]; partials { MS_LEXER_RETURN_TOKEN(PARTIALS); } pattern { MS_LEXER_RETURN_TOKEN(PATTERN); } points { MS_LEXER_RETURN_TOKEN(POINTS); } -items { MS_LEXER_RETURN_TOKEN(ITEMS); } +items { MS_LEXER_RETURN_TOKEN(ITEMS); } position { MS_LEXER_RETURN_TOKEN(POSITION); } postlabelcache { MS_LEXER_RETURN_TOKEN(POSTLABELCACHE); } priority { MS_LEXER_RETURN_TOKEN(PRIORITY); } diff --git a/maplibxml2.c b/maplibxml2.c index 7a0c97ca53..cd3fcfa18a 100644 --- a/maplibxml2.c +++ b/maplibxml2.c @@ -58,7 +58,12 @@ void msLibXml2GenerateList(xmlNodePtr psParent, xmlNsPtr psNs, const char *elnam int i = 0; tokens = msStringSplit(values, delim, &n); for (i=0; i #include "mapserver.h" #include "maptime.h" +#include "mapows.h" #ifdef USE_MSSQL2008 @@ -201,6 +202,7 @@ typedef struct ms_MSSQL2008_layer_info_t { char *user_srid; /* zero length = calculate, non-zero means using this value! */ char *index_name; /* hopefully this isn't necessary - but if the optimizer ain't cuttin' it... */ char *sort_spec; /* the sort by specification which should be applied to the generated select statement */ + SQLSMALLINT *itemtypes; /* storing the sql field types for further reference */ msODBCconn * conn; /* Connection to db */ msGeometryParserInfo gpi; /* struct for the geometry parser */ @@ -602,7 +604,7 @@ static int executeSQL(msODBCconn *conn, const char * sql) } /* Get columns name from query results */ -static int columnName(msODBCconn *conn, int index, char *buffer, int bufferLength) +static int columnName(msODBCconn *conn, int index, char *buffer, int bufferLength, layerObj *layer, char pass_field_def, SQLSMALLINT *itemType) { SQLRETURN rc; @@ -612,6 +614,7 @@ static int columnName(msODBCconn *conn, int index, char *buffer, int bufferLengt SQLULEN columnSize; SQLSMALLINT decimalDigits; SQLSMALLINT nullable; + msMSSQL2008LayerInfo *layerinfo = getMSSQL2008LayerInfo(layer); rc = SQLDescribeCol( conn->hstmt, @@ -629,6 +632,74 @@ static int columnName(msODBCconn *conn, int index, char *buffer, int bufferLengt strlcpy(buffer, (const char *)columnName, bufferLength); else strlcpy(buffer, (const char *)columnName, SQL_COLUMN_NAME_MAX_LENGTH + 1); + + *itemType = dataType; + + if (pass_field_def) { + char md_item_name[256]; + char gml_width[32], gml_precision[32]; + const char *gml_type = NULL; + + gml_width[0] = '\0'; + gml_precision[0] = '\0'; + + switch( dataType ) { + case SQL_INTEGER: + case SQL_SMALLINT: + case SQL_TINYINT: + gml_type = "Integer"; + break; + + case SQL_BIGINT: + gml_type = "Long"; + break; + + case SQL_REAL: + case SQL_FLOAT: + case SQL_DOUBLE: + case SQL_DECIMAL: + case SQL_NUMERIC: + gml_type = "Real"; + if( decimalDigits > 0 ) + sprintf( gml_precision, "%d", decimalDigits ); + break; + + case SQL_TYPE_DATE: + case SQL_TYPE_TIME: + case SQL_TYPE_TIMESTAMP: + gml_type = "Date"; + break; + + case SQL_BIT: + gml_type = "Boolean"; + break; + + default: + gml_type = "Character"; + break; + } + + if( columnSize > 0 ) + sprintf( gml_width, "%d", columnSize ); + + snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", buffer ); + if( msOWSLookupMetadata(&(layer->metadata), "G", "type") == NULL ) + msInsertHashTable(&(layer->metadata), md_item_name, gml_type ); + + snprintf( md_item_name, sizeof(md_item_name), "gml_%s_width", buffer ); + if( strlen(gml_width) > 0 + && msOWSLookupMetadata(&(layer->metadata), "G", "width") == NULL ) + msInsertHashTable(&(layer->metadata), md_item_name, gml_width ); + + snprintf( md_item_name, sizeof(md_item_name), "gml_%s_precision",buffer ); + if( strlen(gml_precision) > 0 + && msOWSLookupMetadata(&(layer->metadata), "G", "precision")==NULL ) + msInsertHashTable(&(layer->metadata), md_item_name, gml_precision ); + + snprintf( md_item_name, sizeof(md_item_name), "gml_%s_nillable",buffer ); + if( nullable > 0 ) + msInsertHashTable(&(layer->metadata), md_item_name, "true" ); + } return 1; } else { setStmntError(conn); @@ -681,6 +752,7 @@ int msMSSQL2008LayerOpen(layerObj *layer) layerinfo->index_name = NULL; layerinfo->sort_spec = NULL; layerinfo->conn = NULL; + layerinfo->itemtypes = NULL; layerinfo->conn = (msODBCconn *) msConnPoolRequest(layer); @@ -726,7 +798,7 @@ int msMSSQL2008LayerOpen(layerObj *layer) "This error occured when trying to make a connection to the specified SQL server. \n" "
\nMost commonly this is caused by
\n" "(1) incorrect connection string
\n" - "(2) you didnt specify a 'user id=...' in your connection string
\n" + "(2) you didn't specify a 'user id=...' in your connection string
\n" "(3) SQL server isnt running
\n" "(4) TCPIP not enabled for SQL Client or server
\n\n", "msMSSQL2008LayerOpen()", maskeddata, errMess); @@ -909,7 +981,19 @@ static int prepare_database(layerObj *layer, rectObj rect, char **query_string) char buffer[10000] = ""; for(t = 0; t < layer->numitems; t++) { + if (layerinfo->itemtypes && (layerinfo->itemtypes[t] == SQL_BINARY || layerinfo->itemtypes[t] == SQL_VARBINARY)) { +#ifdef USE_ICONV + snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "convert(nvarchar(max), convert(varbinary(max),[%s]),2),", layer->items[t]); +#else + snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "convert(varchar(max), convert(varbinary(max),[%s]),2),", layer->items[t]); +#endif + } else { +#ifdef USE_ICONV + snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "convert(nvarchar(max), [%s]),", layer->items[t]); +#else snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "convert(varchar(max), [%s]),", layer->items[t]); +#endif + } } if (layerinfo->geometry_format == MSSQLGEOMETRY_NATIVE) @@ -1131,6 +1215,11 @@ int msMSSQL2008LayerClose(layerObj *layer) layerinfo->geom_table = NULL; } + if(layerinfo->itemtypes) { + msFree(layerinfo->itemtypes); + layerinfo->itemtypes = NULL; + } + setMSSQL2008LayerInfo(layer, NULL); msFree(layerinfo); } @@ -1632,7 +1721,7 @@ int msMSSQL2008LayerGetShapeRandom(layerObj *layer, shapeObj *shape, long *recor if (needLen > 0) { /* allocate the buffer - this will be a null-terminated string so alloc for the null too */ - valueBuffer = (char*) msSmallMalloc( needLen + 1 ); + valueBuffer = (char*) msSmallMalloc( needLen + 2 ); if ( valueBuffer == NULL ) { msSetError( MS_QUERYERR, "Could not allocate value buffer.", "msMSSQL2008LayerGetShapeRandom()" ); return MS_FAILURE; @@ -1647,7 +1736,13 @@ int msMSSQL2008LayerGetShapeRandom(layerObj *layer, shapeObj *shape, long *recor valueBuffer[retLen] = 0; /* null terminate it */ /* Pop the value into the shape's value array */ +#ifdef USE_ICONV + valueBuffer[retLen + 1] = 0; + shape->values[t] = msConvertWideStringToUTF8((wchar_t*)valueBuffer, "UCS-2LE"); + msFree(valueBuffer); +#else shape->values[t] = valueBuffer; +#endif } else /* Copy empty sting for NULL values */ shape->values[t] = msStrdup(""); @@ -1914,6 +2009,13 @@ int msMSSQL2008LayerGetItems(layerObj *layer) char found_geom = 0; int item_num; SQLSMALLINT cols = 0; + const char *value; + /* + * Pass the field definitions through to the layer metadata in the + * "gml_[item]_{type,width,precision}" set of metadata items for + * defining fields. + */ + char pass_field_def = 0; if(layer->debug) { msDebug("in msMSSQL2008LayerGetItems (find column names)\n"); @@ -1951,21 +2053,29 @@ int msMSSQL2008LayerGetItems(layerObj *layer) layer->numitems = cols - 1; /* dont include the geometry column */ layer->items = msSmallMalloc(sizeof(char *) * (layer->numitems + 1)); /* +1 in case there is a problem finding goeometry column */ + layerinfo->itemtypes = msSmallMalloc(sizeof(SQLSMALLINT) * (layer->numitems + 1)); /* it will return an error if there is no geometry column found, */ /* so this isnt a problem */ found_geom = 0; /* havent found the geom field */ item_num = 0; + /* consider populating the field definitions in metadata */ + if((value = msOWSLookupMetadata(&(layer->metadata), "G", "types")) != NULL + && strcasecmp(value,"auto") == 0 ) + pass_field_def = 1; + for(t = 0; t < cols; t++) { char colBuff[256]; + SQLSMALLINT itemType; - columnName(layerinfo->conn, t + 1, colBuff, sizeof(colBuff)); + columnName(layerinfo->conn, t + 1, colBuff, sizeof(colBuff), layer, pass_field_def, &itemType); if(strcmp(colBuff, layerinfo->geom_column) != 0) { /* this isnt the geometry column */ layer->items[item_num] = (char *) msSmallMalloc(strlen(colBuff) + 1); strcpy(layer->items[item_num], colBuff); + layerinfo->itemtypes[item_num] = itemType; item_num++; } else { found_geom = 1; @@ -2099,7 +2209,7 @@ static int msMSSQL2008LayerParseData(layerObj *layer, char **geom_column_name, c } else { slength = strspn(pos_srid + 12, "-0123456789"); if(!slength) { - msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerParseData()", "Error parsing MSSQL2008 data variable: You specified 'using SRID=#' but didnt have any numbers!

\n\nMore Help:

\n\n", data); + msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerParseData()", "Error parsing MSSQL2008 data variable: You specified 'using SRID=#' but didn't have any numbers!

\n\nMore Help:

\n\n", data); msFree(data); return MS_FAILURE; @@ -2271,9 +2381,17 @@ int process_node(layerObj* layer, expressionObj *filter) break; case ')': filter->native_string = msStringConcatenate(filter->native_string, ")"); - break; + break; + /* argument separator */ + case ',': + break; /* literal tokens */ case MS_TOKEN_LITERAL_BOOLEAN: + if(layerinfo->current_node->tokenval.dblval == MS_TRUE) + filter->native_string = msStringConcatenate(filter->native_string, "1"); + else + filter->native_string = msStringConcatenate(filter->native_string, "0"); + break; case MS_TOKEN_LITERAL_NUMBER: strtmpl = "%lf"; snippet = (char *) msSmallMalloc(strlen(strtmpl) + 16); @@ -2350,7 +2468,11 @@ int process_node(layerObj* layer, expressionObj *filter) case MS_TOKEN_BINDING_DOUBLE: case MS_TOKEN_BINDING_INTEGER: case MS_TOKEN_BINDING_STRING: - strtmpl = "%s"; + if(layerinfo->current_node->next->token == MS_TOKEN_COMPARISON_IRE) + strtmpl = "LOWER(%s)"; + else + strtmpl = "%s"; + stresc = msMSSQL2008LayerEscapePropertyName(layer, layerinfo->current_node->tokenval.bindval.item); snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(stresc)); sprintf(snippet, strtmpl, stresc); @@ -2373,9 +2495,85 @@ int process_node(layerObj* layer, expressionObj *filter) case MS_TOKEN_COMPARISON_IN: filter->native_string = msStringConcatenate(filter->native_string, " IN "); break; - case MS_TOKEN_COMPARISON_LIKE: - filter->native_string = msStringConcatenate(filter->native_string, " LIKE "); - break; + case MS_TOKEN_COMPARISON_RE: + case MS_TOKEN_COMPARISON_IRE: + case MS_TOKEN_COMPARISON_LIKE: { + /* process regexp */ + size_t i = 0, j = 0; + char c; + char c_next; + int bCaseInsensitive = (layerinfo->current_node->token == MS_TOKEN_COMPARISON_IRE); + int nEscapeLen = 0; + if (bCaseInsensitive) + filter->native_string = msStringConcatenate(filter->native_string, " LIKE LOWER("); + else + filter->native_string = msStringConcatenate(filter->native_string, " LIKE "); + + layerinfo->current_node = layerinfo->current_node->next; + if (layerinfo->current_node->token != MS_TOKEN_LITERAL_STRING) return 0; + + strtmpl = msStrdup(layerinfo->current_node->tokenval.strval); + if (strtmpl[0] == '/') { + stresc = strtmpl + 1; + strtmpl[strlen(strtmpl) - 1] = '\0'; + } + else if (strtmpl[0] == '^') + stresc = strtmpl + 1; + else + stresc = strtmpl; + + while (*stresc) { + c = stresc[i]; + if (c == '%' || c == '_' || c == '[' || c == ']' || c == '^') { + nEscapeLen++; + } + stresc++; + } + snippet = (char *)msSmallMalloc(strlen(strtmpl) + nEscapeLen + 3); + snippet[j++] = '\''; + while (i < strlen(strtmpl)) { + c = strtmpl[i]; + c_next = strtmpl[i+1]; + + if (i == 0 && c == '^') { + i++; + continue; + } + + if (c == '\\') { + i++; + c = c_next; + } + + if (c == '%' || c == '_' || c == '[' || c == ']' || c == '^') { + snippet[j++] = '\\'; + } + + if (c == '.' && c_next == '*') { + i++; + c = '%'; + } + else if (c == '.') + c = '_'; + + + snippet[j++] = c; + i++; + } + snippet[j++] = '\''; + snippet[j] = '\0'; + + filter->native_string = msStringConcatenate(filter->native_string, snippet); + msFree(strtmpl); + msFree(snippet); + + if (bCaseInsensitive) + filter->native_string = msStringConcatenate(filter->native_string, ")"); + + if (nEscapeLen > 0) + filter->native_string = msStringConcatenate(filter->native_string, " ESCAPE '\\'"); + } + break; case MS_TOKEN_COMPARISON_EQ: filter->native_string = msStringConcatenate(filter->native_string, " = "); break; @@ -2408,67 +2606,131 @@ int process_node(layerObj* layer, expressionObj *filter) /* spatial comparison tokens */ case MS_TOKEN_COMPARISON_INTERSECTS: + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (!process_node(layer, filter)) + return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STIntersects("); - layerinfo->current_node = layerinfo->current_node->next; if (!process_node(layer, filter)) return 0; - filter->native_string = msStringConcatenate(filter->native_string, ")=1"); break; case MS_TOKEN_COMPARISON_DISJOINT: + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (!process_node(layer, filter)) + return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STDisjoint("); - layerinfo->current_node = layerinfo->current_node->next; if (!process_node(layer, filter)) return 0; - filter->native_string = msStringConcatenate(filter->native_string, ")=1"); break; case MS_TOKEN_COMPARISON_TOUCHES: + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (!process_node(layer, filter)) + return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STTouches("); - layerinfo->current_node = layerinfo->current_node->next; if (!process_node(layer, filter)) return 0; - filter->native_string = msStringConcatenate(filter->native_string, ")=1"); break; case MS_TOKEN_COMPARISON_OVERLAPS: + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (!process_node(layer, filter)) + return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STOverlaps("); - layerinfo->current_node = layerinfo->current_node->next; if (!process_node(layer, filter)) return 0; - filter->native_string = msStringConcatenate(filter->native_string, ")=1"); break; case MS_TOKEN_COMPARISON_CROSSES: + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (!process_node(layer, filter)) + return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STCrosses("); - layerinfo->current_node = layerinfo->current_node->next; if (!process_node(layer, filter)) return 0; - filter->native_string = msStringConcatenate(filter->native_string, ")=1"); break; case MS_TOKEN_COMPARISON_WITHIN: + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (!process_node(layer, filter)) + return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STWithin("); - layerinfo->current_node = layerinfo->current_node->next; if (!process_node(layer, filter)) return 0; - filter->native_string = msStringConcatenate(filter->native_string, ")=1"); break; case MS_TOKEN_COMPARISON_CONTAINS: + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (!process_node(layer, filter)) + return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STContains("); - layerinfo->current_node = layerinfo->current_node->next; if (!process_node(layer, filter)) return 0; - filter->native_string = msStringConcatenate(filter->native_string, ")=1"); break; case MS_TOKEN_COMPARISON_EQUALS: + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (!process_node(layer, filter)) + return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STEquals("); - layerinfo->current_node = layerinfo->current_node->next; if (!process_node(layer, filter)) return 0; - filter->native_string = msStringConcatenate(filter->native_string, ")=1"); break; case MS_TOKEN_COMPARISON_BEYOND: @@ -2481,24 +2743,44 @@ int process_node(layerObj* layer, expressionObj *filter) /* spatial functions */ case MS_TOKEN_FUNCTION_AREA: - filter->native_string = msStringConcatenate(filter->native_string, ".STArea("); - layerinfo->current_node = layerinfo->current_node->next; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; if (!process_node(layer, filter)) return 0; - filter->native_string = msStringConcatenate(filter->native_string, ")"); + filter->native_string = msStringConcatenate(filter->native_string, ".STArea()"); break; case MS_TOKEN_FUNCTION_BUFFER: + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (!process_node(layer, filter)) + return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STBuffer("); - layerinfo->current_node = layerinfo->current_node->next; if (!process_node(layer, filter)) return 0; filter->native_string = msStringConcatenate(filter->native_string, ")"); break; case MS_TOKEN_FUNCTION_DIFFERENCE: + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (!process_node(layer, filter)) + return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; + if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; + else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STDifference("); - layerinfo->current_node = layerinfo->current_node->next; if (!process_node(layer, filter)) return 0; filter->native_string = msStringConcatenate(filter->native_string, ")"); diff --git a/mapogcfilter.c b/mapogcfilter.c index 05f017a34d..e0387f89f6 100644 --- a/mapogcfilter.c +++ b/mapogcfilter.c @@ -42,7 +42,9 @@ #include "mapows.h" #include +#if 0 static int FLTHasUniqueTopLevelDuringFilter(FilterEncodingNode *psFilterNode); +#endif int FLTIsNumeric(const char *pszValue) { @@ -162,7 +164,8 @@ char *FLTGetExpressionForValuesRanges(layerObj *lp, const char *item, const char if (paszElements && numelements > 0) { if (forcecharcter) bIscharacter = MS_TRUE; - bIscharacter= !FLTIsNumeric(paszElements[0]); + else + bIscharacter= !FLTIsNumeric(paszElements[0]); pszTmpExpression = msStringConcatenate(pszTmpExpression, "("); for (i=0; iconnectiontype == MS_OGR && !FLTHasUniqueTopLevelDuringFilter(psNode)) ) { - return FLTApplySimpleSQLFilter(psNode, map, iLayerIndex); + return FLTLayerApplyPlainFilterToLayer(psNode, map, iLayerIndex); +} + + +/************************************************************************/ +/* FLTGetTopBBOX */ +/* */ +/* Return the "top" BBOX if there's a unique one. */ +/************************************************************************/ +static int FLTGetTopBBOXInternal(FilterEncodingNode *psNode, FilterEncodingNode** ppsTopBBOX, int *pnCount) +{ + if (psNode->pszValue && strcasecmp(psNode->pszValue, "BBOX") == 0) { + (*pnCount) ++; + if( *pnCount == 1 ) + { + *ppsTopBBOX = psNode; + return TRUE; + } + *ppsTopBBOX = NULL; + return FALSE; + } + else if (psNode->pszValue && strcasecmp(psNode->pszValue, "AND") == 0) { + return FLTGetTopBBOXInternal(psNode->psLeftNode, ppsTopBBOX, pnCount) && + FLTGetTopBBOXInternal(psNode->psRightNode, ppsTopBBOX, pnCount); + } + else + { + return TRUE; } +} - return FLTLayerApplyPlainFilterToLayer(psNode, map, iLayerIndex); +static FilterEncodingNode* FLTGetTopBBOX(FilterEncodingNode *psNode) +{ + int nCount = 0; + FilterEncodingNode* psTopBBOX = NULL; + FLTGetTopBBOXInternal(psNode, &psTopBBOX, &nCount); + return psTopBBOX; } /************************************************************************/ @@ -637,12 +664,66 @@ int FLTLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map, { char *pszExpression =NULL; int status =MS_FALSE; + layerObj* lp = GET_LAYER(map, iLayerIndex); - pszExpression = FLTGetCommonExpression(psNode, GET_LAYER(map, iLayerIndex)); - if(map->debug == MS_DEBUGLEVEL_VVV) - msDebug("FLTLayerApplyPlainFilterToLayer(): %s\n", pszExpression); + pszExpression = FLTGetCommonExpression(psNode, lp); if (pszExpression) { - status = FLTApplyFilterToLayerCommonExpression(map, iLayerIndex, pszExpression); + const char* pszUseDefaultExtent; + FilterEncodingNode* psTopBBOX; + rectObj rect = map->extent; + + pszUseDefaultExtent = msOWSLookupMetadata(&(lp->metadata), "F", + "use_default_extent_for_getfeature"); + if( pszUseDefaultExtent && !CSLTestBoolean(pszUseDefaultExtent) && + lp->connectiontype == MS_OGR ) + { + const rectObj rectInvalid = MS_INIT_INVALID_RECT; + rect = rectInvalid; + } + + psTopBBOX = FLTGetTopBBOX(psNode); + if( psTopBBOX ) + { + int can_remove_expression = MS_TRUE; + const char* pszEPSG = FLTGetBBOX(psNode, &rect); + if(pszEPSG && map->projection.numargs > 0) { + projectionObj sProjTmp; + msInitProjection(&sProjTmp); + /* Use the non EPSG variant since axis swapping is done in FLTDoAxisSwappingIfNecessary */ + if (msLoadProjectionString(&sProjTmp, pszEPSG) == 0) { + rectObj oldRect = rect; + msProjectRect(&sProjTmp, &map->projection, &rect); + /* If reprojection is involved, do not remove the expression */ + if( rect.minx != oldRect.minx || + rect.miny != oldRect.miny || + rect.maxx != oldRect.maxx || + rect.maxy != oldRect.maxy ) + { + can_remove_expression = MS_FALSE; + } + } + msFreeProjection(&sProjTmp); + } + + /* Small optimization: if the query is just a BBOX, then do a */ + /* msQueryByRect() */ + if( psTopBBOX == psNode && can_remove_expression ) + { + msFree(pszExpression); + pszExpression = NULL; + } + } + + if(map->debug == MS_DEBUGLEVEL_VVV) + { + if( pszExpression ) + msDebug("FLTLayerApplyPlainFilterToLayer(): %s, rect=%.15g,%.15g,%.15g,%.15g\n", pszExpression, rect.minx, rect.miny, rect.maxx, rect.maxy); + else + msDebug("FLTLayerApplyPlainFilterToLayer(): rect=%.15g,%.15g,%.15g,%.15g\n", rect.minx, rect.miny, rect.maxx, rect.maxy); + } + + status = FLTApplyFilterToLayerCommonExpressionWithRect(map, iLayerIndex, + pszExpression, rect); msFree(pszExpression); } @@ -756,7 +837,7 @@ static int FLTIsGeometryFilterNodeType(int eType) /************************************************************************/ /* FLTFreeFilterEncodingNode */ /* */ -/* recursive freeing of Filer Encoding nodes. */ +/* recursive freeing of Filter Encoding nodes. */ /************************************************************************/ void FLTFreeFilterEncodingNode(FilterEncodingNode *psFilterNode) { @@ -803,7 +884,7 @@ void FLTFreeFilterEncodingNode(FilterEncodingNode *psFilterNode) /************************************************************************/ /* FLTCreateFilterEncodingNode */ /* */ -/* return a FilerEncoding node. */ +/* return a FilterEncoding node. */ /************************************************************************/ FilterEncodingNode *FLTCreateFilterEncodingNode(void) { @@ -928,8 +1009,8 @@ static CPLXMLNode* FLTGetNextSibblingNode(CPLXMLNode* psXMLNode) /************************************************************************/ /* FLTInsertElementInNode */ /* */ -/* Utility function to parse an XML node and transfter the */ -/* contennts into the Filer Encoding node structure. */ +/* Utility function to parse an XML node and transfer the */ +/* contents into the Filter Encoding node structure. */ /************************************************************************/ void FLTInsertElementInNode(FilterEncodingNode *psFilterNode, CPLXMLNode *psXMLNode) @@ -1784,6 +1865,7 @@ int FLTValidForBBoxFilter(FilterEncodingNode *psFilterNode) return 0; } +#if 0 static int FLTHasUniqueTopLevelDuringFilter(FilterEncodingNode *psFilterNode) { int nCount = 0; @@ -1809,7 +1891,7 @@ static int FLTHasUniqueTopLevelDuringFilter(FilterEncodingNode *psFilterNode) return 0; } - +#endif int FLTIsLineFilter(FilterEncodingNode *psFilterNode) { @@ -1994,7 +2076,7 @@ const char* FLTGetDuring(FilterEncodingNode *psFilterNode, const char** ppszTime /************************************************************************/ /* GetMapserverExpression */ /* */ -/* Return a mapserver expression base on the Filer encoding nodes. */ +/* Return a mapserver expression base on the Filter encoding nodes. */ /************************************************************************/ char *FLTGetMapserverExpression(FilterEncodingNode *psFilterNode, layerObj *lp) { @@ -2923,6 +3005,8 @@ char *FLTGetIsLikeComparisonExpression(FilterEncodingNode *psFilterNode) pszValue = psFilterNode->psRightNode->pszValue; nLength = strlen(pszValue); + if( 1 + 2 * nLength + 1 + 1 >= sizeof(szTmp) ) + return NULL; iTmp =0; if (nLength > 0 && pszValue[0] != pszWild[0] && @@ -3596,6 +3680,57 @@ int FLTCheckInvalidOperand(FilterEncodingNode *psFilterNode) return status; } +/************************************************************************/ +/* FLTProcessPropertyIsNull */ +/* */ +/* HACK for PropertyIsNull processing. PostGIS & Spatialite only */ +/* for now. */ +/************************************************************************/ +int FLTProcessPropertyIsNull(FilterEncodingNode *psFilterNode, + mapObj *map, int i) +{ + int status = MS_SUCCESS; + + if (psFilterNode->eType == FILTER_NODE_TYPE_COMPARISON && + psFilterNode->psLeftNode != NULL && + psFilterNode->psLeftNode->eType == FILTER_NODE_TYPE_PROPERTYNAME && + strcmp(psFilterNode->pszValue, "PropertyIsNull") == 0 && + !FLTIsGMLDefaultProperty(psFilterNode->psLeftNode->pszValue) ) + { + layerObj* lp; + int layerWasOpened; + + lp = GET_LAYER(map, i); + layerWasOpened = msLayerIsOpen(lp); + + /* Horrible HACK to compensate for the lack of null testing in MapServer */ + if( (lp->connectiontype == MS_POSTGIS || + (lp->connectiontype == MS_OGR && msOGRIsSpatialite(lp))) && + strcmp(psFilterNode->pszValue, "PropertyIsNull") == 0 ) + { + msFree(psFilterNode->pszValue); + psFilterNode->pszValue = msStrdup("PropertyIsEqualTo"); + psFilterNode->psRightNode = FLTCreateBinaryCompFilterEncodingNode(); + psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_LITERAL; + psFilterNode->psRightNode->pszValue = msStrdup("_MAPSERVER_NULL_"); + } + + if (!layerWasOpened) /* do not close the layer if it has been opened somewhere else (paging?) */ + msLayerClose(lp); + } + + if (psFilterNode->psLeftNode) + { + status = FLTProcessPropertyIsNull(psFilterNode->psLeftNode, map, i); + if( status == MS_SUCCESS ) + { + if (psFilterNode->psRightNode) + status = FLTProcessPropertyIsNull(psFilterNode->psRightNode, map, i); + } + } + return status; +} + /************************************************************************/ /* FLTCheckInvalidProperty */ /* */ diff --git a/mapogcfilter.h b/mapogcfilter.h index 7d7828d364..feff2c26cc 100644 --- a/mapogcfilter.h +++ b/mapogcfilter.h @@ -148,6 +148,9 @@ int FLTCheckInvalidProperty(FilterEncodingNode *psFilterNode, mapObj *map, int i); FilterEncodingNode* FLTSimplify(FilterEncodingNode *psFilterNode, int* pnEvaluation); +int FLTApplyFilterToLayerCommonExpressionWithRect(mapObj *map, int iLayerIndex, const char *pszExpression, rectObj rect); +int FLTProcessPropertyIsNull(FilterEncodingNode *psFilterNode, + mapObj *map, int i); #endif diff --git a/mapogcfiltercommon.c b/mapogcfiltercommon.c index 3105d3ff9b..600ab09248 100644 --- a/mapogcfiltercommon.c +++ b/mapogcfiltercommon.c @@ -68,7 +68,7 @@ char *FLTGetIsLikeComparisonCommonExpression(FilterEncodingNode *psFilterNode) /* Use operand with regular expressions. */ /* -------------------------------------------------------------------- */ szBuffer[0] = '\0'; - sprintf(szTmp, "%s", " (\"["); + sprintf(szTmp, "%s", "(\"["); szTmp[4] = '\0'; strlcat(szBuffer, szTmp, bufferSize); @@ -88,6 +88,8 @@ char *FLTGetIsLikeComparisonCommonExpression(FilterEncodingNode *psFilterNode) pszValue = psFilterNode->psRightNode->pszValue; nLength = strlen(pszValue); + if( 1 + 2 * nLength + 1 + 1 >= sizeof(szTmp) ) + return NULL; iTmp =0; if (nLength > 0 && pszValue[0] != pszWild[0] && pszValue[0] != pszSingle[0] && pszValue[0] != pszEscape[0]) { @@ -174,9 +176,9 @@ char *FLTGetIsBetweenComparisonCommonExpresssion(FilterEncodingNode *psFilterNod /* -------------------------------------------------------------------- */ /* attribute */ if (bString) - sprintf(szBuffer, "%s", " (\"["); + sprintf(szBuffer, "%s", "(\"["); else - sprintf(szBuffer, "%s", " (["); + sprintf(szBuffer, "%s", "(["); pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, psFilterNode->psLeftNode->pszValue); @@ -288,9 +290,9 @@ char *FLTGetBinaryComparisonCommonExpression(FilterEncodingNode *psFilterNode, l /* attribute */ if (bString) - sprintf(szTmp, "%s", " (\"["); + sprintf(szTmp, "%s", "(\"["); else - sprintf(szTmp, "%s"," (["); + sprintf(szTmp, "%s","(["); pszExpression = msStringConcatenate(pszExpression, szTmp); pszExpression = msStringConcatenate(pszExpression, psFilterNode->psLeftNode->pszValue); @@ -307,19 +309,20 @@ char *FLTGetBinaryComparisonCommonExpression(FilterEncodingNode *psFilterNode, l else sprintf(szTmp, "%s", "="); } else if (strcasecmp(psFilterNode->pszValue, "PropertyIsNotEqualTo") == 0) - sprintf(szTmp, "%s", " != "); + sprintf(szTmp, "%s", "!="); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLessThan") == 0) - sprintf(szTmp, "%s", " < "); + sprintf(szTmp, "%s", "<"); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsGreaterThan") == 0) - sprintf(szTmp, "%s", " > "); + sprintf(szTmp, "%s", ">"); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLessThanOrEqualTo") == 0) - sprintf(szTmp, "%s", " <= "); + sprintf(szTmp, "%s", "<="); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsGreaterThanOrEqualTo") == 0) - sprintf(szTmp, "%s", " >= "); + sprintf(szTmp, "%s", ">="); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0) - sprintf(szTmp, "%s", " ~ "); + sprintf(szTmp, "%s", "~"); pszExpression = msStringConcatenate(pszExpression, szTmp); + pszExpression = msStringConcatenate(pszExpression, " "); /* value */ if (bString) { @@ -356,7 +359,6 @@ char *FLTGetLogicalComparisonCommonExpression(FilterEncodingNode *psFilterNode, { char *pszExpression = NULL; char *pszTmp = NULL; - char szBuffer[256]; if (!psFilterNode || !FLTIsLogicalFilterType(psFilterNode->pszValue)) return NULL; @@ -369,17 +371,16 @@ char *FLTGetLogicalComparisonCommonExpression(FilterEncodingNode *psFilterNode, if (!pszTmp) return NULL; - sprintf(szBuffer, "%s", " ("); - pszExpression = msStringConcatenate(pszExpression, szBuffer); + pszExpression = msStringConcatenate(pszExpression, "("); pszExpression = msStringConcatenate(pszExpression, pszTmp); msFree(pszTmp); - sprintf(szBuffer, "%s", " "); - pszExpression = msStringConcatenate(pszExpression, szBuffer); + pszExpression = msStringConcatenate(pszExpression, " "); pszExpression = msStringConcatenate(pszExpression, psFilterNode->pszValue); - sprintf(szBuffer, "%s", " "); + + pszExpression = msStringConcatenate(pszExpression, " "); pszTmp = FLTGetCommonExpression(psFilterNode->psRightNode, lp); if (!pszTmp) { @@ -390,8 +391,7 @@ char *FLTGetLogicalComparisonCommonExpression(FilterEncodingNode *psFilterNode, pszExpression = msStringConcatenate(pszExpression, pszTmp); msFree(pszTmp); - sprintf(szBuffer, "%s", ") "); - pszExpression = msStringConcatenate(pszExpression, szBuffer); + pszExpression = msStringConcatenate(pszExpression, ")"); } /* -------------------------------------------------------------------- */ /* NOT */ @@ -401,14 +401,12 @@ char *FLTGetLogicalComparisonCommonExpression(FilterEncodingNode *psFilterNode, if (!pszTmp) return NULL; - sprintf(szBuffer, "%s", " (NOT "); - pszExpression = msStringConcatenate(pszExpression, szBuffer); + pszExpression = msStringConcatenate(pszExpression, "(NOT "); pszExpression = msStringConcatenate(pszExpression, pszTmp); msFree(pszTmp); - sprintf(szBuffer, "%s", ") "); - pszExpression = msStringConcatenate(pszExpression, szBuffer); + pszExpression = msStringConcatenate(pszExpression, ")"); } return pszExpression; @@ -693,6 +691,12 @@ char *FLTGetCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp) } int FLTApplyFilterToLayerCommonExpression(mapObj *map, int iLayerIndex, const char *pszExpression) +{ + return FLTApplyFilterToLayerCommonExpressionWithRect(map, iLayerIndex, pszExpression, map->extent); +} + +/* rect must be in map->projection */ +int FLTApplyFilterToLayerCommonExpressionWithRect(mapObj *map, int iLayerIndex, const char *pszExpression, rectObj rect) { int retval; int save_startindex; @@ -707,18 +711,25 @@ int FLTApplyFilterToLayerCommonExpression(mapObj *map, int iLayerIndex, const ch map->query.maxfeatures = save_maxfeatures; map->query.only_cache_result_count = save_only_cache_result_count; - map->query.type = MS_QUERY_BY_FILTER; map->query.mode = MS_QUERY_MULTIPLE; - - msInitExpression(&map->query.filter); - map->query.filter.string = msStrdup(pszExpression); - map->query.filter.type = MS_EXPRESSION; /* a logical expression */ map->query.layer = iLayerIndex; - /* TODO: if there is a bbox in the node, get it and set the map extent (projected to map->projection */ - map->query.rect = map->extent; + map->query.rect = rect; - retval = msQueryByFilter(map); + if( pszExpression ) + { + map->query.type = MS_QUERY_BY_FILTER; + msInitExpression(&map->query.filter); + map->query.filter.string = msStrdup(pszExpression); + map->query.filter.type = MS_EXPRESSION; /* a logical expression */ + + retval = msQueryByFilter(map); + } + else + { + map->query.type = MS_QUERY_BY_RECT; + retval = msQueryByRect(map); + } return retval; } diff --git a/mapogcsld.c b/mapogcsld.c index 465421d478..00afe03e8c 100644 --- a/mapogcsld.c +++ b/mapogcsld.c @@ -106,6 +106,7 @@ int msSLDApplySLDURL(mapObj *map, char *szURL, int iLayer, unlink(pszSLDTmpFile); msSetError(MS_WMSERR, "Could not open SLD %s and save it in a temporary file. Please make sure that the sld url is valid and that the temporary path is set. The temporary path can be defined for example by setting TMPPATH in the map file. Please check the MapServer documentation on temporary path settings.", "msSLDApplySLDURL", szURL); } + msFree(pszSLDTmpFile); if (pszSLDbuf) nStatus = msSLDApplySLD(map, pszSLDbuf, iLayer, pszStyleLayerName, ppszLayerNames); } @@ -328,7 +329,7 @@ int msSLDApplySLD(mapObj *map, char *psSLDXML, int iLayer, char *pszStyleLayerNa /* opacity for sld raster */ if (GET_LAYER(map, i)->type == MS_LAYER_RASTER && - pasLayers[i].compositer && pasLayers[j].compositer->opacity != 100) + pasLayers[j].compositer && pasLayers[j].compositer->opacity != 100) msSetLayerOpacity(GET_LAYER(map, i), pasLayers[j].compositer->opacity); /* mark as auto-generate SLD */ @@ -3417,7 +3418,7 @@ char *msSLDGetGraphicSLD(styleObj *psStyle, layerObj *psLayer, } } else bGenerateDefaultSymbol =1; - } else if (psSymbol->type == MS_SYMBOL_PIXMAP) { + } else if (psSymbol->type == MS_SYMBOL_PIXMAP || psSymbol->type == MS_SYMBOL_SVG) { if (psSymbol->name) { pszURL = msLookupHashTable(&(psLayer->metadata), "WMS_SLD_SYMBOL_URL"); if (!pszURL) @@ -3454,8 +3455,8 @@ char *msSLDGetGraphicSLD(styleObj *psStyle, layerObj *psLayer, snprintf(szTmp, sizeof(szTmp), "<%sFormat>image/png\n", sNameSpace, sNameSpace); } else - snprintf(szTmp, sizeof(szTmp), "<%sFormat>%s\n", "image/gif", - sNameSpace, sNameSpace); + snprintf(szTmp, sizeof(szTmp), "<%sFormat>%s\n", sNameSpace, + (psSymbol->type ==MS_SYMBOL_SVG)?"image/svg+xml":"image/gif",sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); diff --git a/mapogcsos.c b/mapogcsos.c index f709c4882f..5ee9babd21 100644 --- a/mapogcsos.c +++ b/mapogcsos.c @@ -284,7 +284,7 @@ void msSOSAddPropertyNode(xmlNsPtr psNsSwe, xmlNsPtr psNsXLink, xmlNodePtr psPar pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_name"); if (pszValue) - psNode = xmlNewChild(psCompNode, psNsGml, + psNode = xmlNewTextChild(psCompNode, psNsGml, BAD_CAST "name", BAD_CAST pszValue); /* add components */ @@ -1340,6 +1340,8 @@ int msSOSGetCapabilities(mapObj *map, sosParamsObj *sosparams, cgiRequestObj *re break; } + lp = (GET_LAYER(map, j)); + /*description*/ value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_description"); @@ -1349,7 +1351,6 @@ int msSOSGetCapabilities(mapObj *map, sosParamsObj *sosparams, cgiRequestObj *re xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"sos_offering_description\" missing for gml:description")); /*name*/ - lp = (GET_LAYER(map, j)); /*first layer*/ value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_name"); if (value) psNode = xmlNewChild(psOfferingNode, psNsGml, BAD_CAST "name", BAD_CAST value); diff --git a/mapogr.cpp b/mapogr.cpp index 881250f5f5..e08f8d4286 100644 --- a/mapogr.cpp +++ b/mapogr.cpp @@ -33,6 +33,8 @@ #include "mapproject.h" #include "mapthread.h" #include "mapows.h" +#include +#include #if defined(USE_OGR) || defined(USE_GDAL) # include "gdal_version.h" @@ -46,6 +48,7 @@ #ifdef USE_OGR +// GDAL 1.x API #include "ogr_api.h" typedef struct ms_ogr_file_info_t { @@ -59,10 +62,25 @@ typedef struct ms_ogr_file_info_t { int nTileId; /* applies on the tiles themselves. */ struct ms_ogr_file_info_t *poCurTile; /* exists on tile index, -> tiles */ - rectObj rect; /* set by WhichShapes */ + bool rect_is_defined; + rectObj rect; /* set by TranslateMsExpression (possibly) and WhichShapes */ int last_record_index_read; + const char* dialect; /* NULL, Spatialite or PostgreSQL */ + char *pszSelect; + char *pszSpatialFilterTableName; + char *pszSpatialFilterGeometryColumn; + char *pszMainTableName; + char *pszRowId; + int bIsOKForSQLCompose; + bool bHasSpatialIndex; // used only for spatialite for now + char* pszTablePrefix; // prefix to qualify field names. used only for spatialite for now when a join is done for spatial filtering. + + int bPaging; + + char* pszWHERE; + } msOGRFileInfo; static int msOGRLayerIsOpen(layerObj *layer); @@ -490,6 +508,9 @@ int msOGRGeometryToShape(OGRGeometryH hGeometry, shapeObj *psShape, // Special field index codes for handling text string and angle coming from // OGR style strings. + +#define MSOGR_FID_INDEX -99 + #define MSOGR_LABELNUMITEMS 21 #define MSOGR_LABELFONTNAMENAME "OGR:LabelFont" #define MSOGR_LABELFONTNAMEINDEX -100 @@ -588,6 +609,9 @@ static char **msOGRGetValues(layerObj *layer, OGRFeatureH hFeature) if (itemindexes[i] >= 0) { // Extract regular attributes values[i] = msStrdup(OGR_F_GetFieldAsString( hFeature, itemindexes[i])); + } else if (itemindexes[i] == MSOGR_FID_INDEX ) { + values[i] = msStrdup(CPLSPrintf(CPL_FRMT_GIB, + (GIntBig) OGR_F_GetFID(hFeature))); } else { // Handle special OGR attributes coming from StyleString if (!hStyleMgr) { @@ -1069,6 +1093,10 @@ void msOGRInitialize(void) #ifdef USE_OGR +static void msOGRFileOpenSpatialite( layerObj *layer, + const char *pszLayerDef, + msOGRFileInfo *psInfo ); + /********************************************************************** * msOGRFileOpen() * @@ -1166,16 +1194,13 @@ msOGRFileOpen(layerObj *layer, const char *connection ) RELEASE_OGR_LOCK; if( hDS == NULL ) { - if( strlen(CPLGetLastErrorMsg()) == 0 ) - msSetError(MS_OGRERR, + msSetError(MS_OGRERR, "Open failed for OGR connection in layer `%s'. " - "File not found or unsupported format.", + "File not found or unsupported format. Check server logs.", "msOGRFileOpen()", layer->name?layer->name:"(null)" ); - else - msSetError(MS_OGRERR, - "Open failed for OGR connection in layer `%s'.\n%s\n", - "msOGRFileOpen()", + if( strlen(CPLGetLastErrorMsg()) == 0 ) + msDebug("Open failed for OGR connection in layer `%s'.\n%s\n", layer->name?layer->name:"(null)", CPLGetLastErrorMsg() ); CPLFree( pszDSName ); @@ -1203,9 +1228,11 @@ msOGRFileOpen(layerObj *layer, const char *connection ) hLayer = OGR_DS_ExecuteSQL( hDS, pszLayerDef, NULL, NULL ); if( hLayer == NULL ) { msSetError(MS_OGRERR, - "ExecuteSQL(%s) failed.\n%s", - "msOGRFileOpen()", - pszLayerDef, CPLGetLastErrorMsg() ); + "ExecuteSQL() failed. Check server logs.", + "msOGRFileOpen()"); + if( strlen(CPLGetLastErrorMsg()) == 0 ) + msDebug("ExecuteSQL(%s) failed.\n%s\n", + pszLayerDef, CPLGetLastErrorMsg() ); RELEASE_OGR_LOCK; msConnPoolRelease( layer, hDS ); CPLFree( pszLayerDef ); @@ -1237,9 +1264,11 @@ msOGRFileOpen(layerObj *layer, const char *connection ) } if (hLayer == NULL) { - msSetError(MS_OGRERR, "GetLayer(%s) failed for OGR connection `%s'.", + msSetError(MS_OGRERR, "GetLayer(%s) failed for OGR connection. Check logs.", "msOGRFileOpen()", - pszLayerDef, connection ); + pszLayerDef); + msDebug("GetLayer(%s) failed for OGR connection `%s'.\n", + pszLayerDef, connection ); CPLFree( pszLayerDef ); msConnPoolRelease( layer, hDS ); return NULL; @@ -1258,13 +1287,366 @@ msOGRFileOpen(layerObj *layer, const char *connection ) psInfo->nTileId = 0; psInfo->poCurTile = NULL; + psInfo->rect_is_defined = false; psInfo->rect.minx = psInfo->rect.maxx = 0; psInfo->rect.miny = psInfo->rect.maxy = 0; psInfo->last_record_index_read = -1; + psInfo->dialect = NULL; + + psInfo->pszSelect = NULL; + psInfo->pszSpatialFilterTableName = NULL; + psInfo->pszSpatialFilterGeometryColumn = NULL; + psInfo->pszMainTableName = NULL; + psInfo->pszRowId = NULL; + psInfo->bIsOKForSQLCompose = true; + psInfo->bPaging = false; + psInfo->bHasSpatialIndex = false; + psInfo->pszTablePrefix = NULL; + psInfo->pszWHERE = NULL; + + // GDAL 1.x API + OGRSFDriverH dr = OGR_DS_GetDriver(hDS); + const char *name = OGR_Dr_GetName(dr); + if (strcmp(name, "SQLite") == 0) { + bool have_spatialite = false; + + CPLPushErrorHandler(CPLQuietErrorHandler); + + // test for Spatialite support in driver + const char *test_spatialite = "SELECT spatialite_version()"; + OGRLayerH l = OGR_DS_ExecuteSQL(hDS, test_spatialite, NULL, NULL); + if (l) { + OGR_DS_ReleaseResultSet(hDS, l); + have_spatialite = true; + } + + // test for Spatialite enabled db + if (have_spatialite) { + have_spatialite = false; + const char *test_sql = "select 1 from sqlite_master where name = 'geometry_columns' and sql LIKE '%spatial_index_enabled%'"; + OGRLayerH l = OGR_DS_ExecuteSQL(hDS, test_sql, NULL, NULL); + if (l) { + if (OGR_L_GetFeatureCount(l, TRUE) == 1) + have_spatialite = true; + OGR_DS_ReleaseResultSet(hDS, l); + } + } + + CPLPopErrorHandler(); + CPLErrorReset(); + + if (have_spatialite) + psInfo->dialect = "Spatialite"; + else + msDebug("msOGRFileOpen: Native SQL not available, no Spatialite support and/or not a Spatialite enabled db\n"); + } else if (strcmp(name, "PostgreSQL") == 0) { + psInfo->dialect = "PostgreSQL"; + // todo: PostgreSQL not yet tested + + } else if (strcmp(name, "GPKG") == 0 && nLayerIndex >= 0 && + atoi(GDALVersionInfo("VERSION_NUM")) >= 2000000) { + + bool has_rtree = false; + const char* test_rtree = + CPLSPrintf("SELECT 1 FROM sqlite_master WHERE name = 'rtree_%s_%s'", + OGR_L_GetName(hLayer), OGR_L_GetGeometryColumn(hLayer)); + OGRLayerH l = OGR_DS_ExecuteSQL(hDS, test_rtree, NULL, NULL); + if( l ) + { + if( OGR_L_GetFeatureCount(l, TRUE) == 1 ) + { + has_rtree = true; + } + OGR_DS_ReleaseResultSet(hDS, l); + } + if( has_rtree ) + { + bool have_gpkg_spatialite = false; + + CPLPushErrorHandler(CPLQuietErrorHandler); + + // test for Spatialite >= 4.3 support in driver + const char *test_spatialite = "SELECT spatialite_version()"; + l = OGR_DS_ExecuteSQL(hDS, test_spatialite, NULL, NULL); + if (l) { + OGRFeatureH hFeat = OGR_L_GetNextFeature(l); + if( hFeat ) + { + const char* pszVersion = OGR_F_GetFieldAsString(hFeat, 0); + have_gpkg_spatialite = atof(pszVersion) >= 4.3; + OGR_F_Destroy(hFeat); + } + OGR_DS_ReleaseResultSet(hDS, l); + } + CPLPopErrorHandler(); + CPLErrorReset(); + + if( have_gpkg_spatialite ) + { + psInfo->pszMainTableName = msStrdup( OGR_L_GetName(hLayer) ); + psInfo->pszSpatialFilterTableName = msStrdup( OGR_L_GetName(hLayer) ); + psInfo->pszSpatialFilterGeometryColumn = msStrdup( OGR_L_GetGeometryColumn(hLayer) ); + psInfo->dialect = "GPKG"; + psInfo->bPaging = true; + psInfo->bHasSpatialIndex = true; + } + else + msDebug("msOGRFileOpen: Spatialite support in GPKG not enabled\n"); + } + else + { + msDebug("msOGRFileOpen: RTree index not available\n"); + } + } + + if( psInfo->dialect != NULL && EQUAL(psInfo->dialect, "Spatialite") ) + msOGRFileOpenSpatialite(layer, pszLayerDef, psInfo); return psInfo; } +/************************************************************************/ +/* msOGRFileOpenSpatialite() */ +/************************************************************************/ + +static void msOGRFileOpenSpatialite( layerObj *layer, + const char* pszLayerDef, + msOGRFileInfo *psInfo ) +{ + // In the case of a SQLite DB, check that we can identify the + // underlying table + if( psInfo->nLayerIndex == -1 ) + { + psInfo->bIsOKForSQLCompose = false; + + const char* from = strstr( psInfo->pszLayerDef, " from "); + if( from == NULL ) + from = strstr( psInfo->pszLayerDef, " FROM "); + if( from ) + { + const char* pszBeginningOfTable = from + strlen(" FROM "); + const char* pszIter = pszBeginningOfTable; + while( *pszIter && *pszIter != ' ' ) + pszIter ++; + if( strchr(pszIter, ',') == NULL && + strstr(pszIter, " where ") == NULL && strstr(pszIter, " WHERE ") == NULL && + strstr(pszIter, " join ") == NULL && strstr(pszIter, " JOIN ") == NULL && + strstr(pszIter, " order by ") == NULL && strstr(pszIter, " ORDER BY ") == NULL) + { + psInfo->bIsOKForSQLCompose = true; + psInfo->pszMainTableName = msStrdup(pszBeginningOfTable); + psInfo->pszMainTableName[pszIter - pszBeginningOfTable] = '\0'; + psInfo->pszSpatialFilterTableName = msStrdup(psInfo->pszMainTableName); + psInfo->pszSpatialFilterGeometryColumn = msStrdup( OGR_L_GetGeometryColumn(psInfo->hLayer) ); + + char* pszRequest = NULL; + pszRequest = msStringConcatenate(pszRequest, + "SELECT name FROM sqlite_master WHERE type = 'table' AND name = lower('"); + pszRequest = msStringConcatenate(pszRequest, psInfo->pszMainTableName); + pszRequest = msStringConcatenate(pszRequest, "')"); + OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL ); + msFree(pszRequest); + + if( hLayer ) + { + OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer); + psInfo->bIsOKForSQLCompose = (hFeature != NULL); + if( hFeature ) + { + msFree(psInfo->pszMainTableName); + msFree(psInfo->pszSpatialFilterTableName); + psInfo->pszMainTableName = msStrdup( OGR_F_GetFieldAsString( hFeature, 0) ); + psInfo->pszSpatialFilterTableName = msStrdup( psInfo->pszMainTableName ); + OGR_F_Destroy(hFeature); + } + OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer ); + } + if( psInfo->bIsOKForSQLCompose ) + { + psInfo->pszSelect = msStrdup(psInfo->pszLayerDef); + } + else + { + // Test if it is a spatial view + pszRequest = msStringConcatenate(NULL, + "SELECT f_table_name, f_geometry_column, view_rowid FROM views_geometry_columns WHERE view_name = lower('"); + pszRequest = msStringConcatenate(pszRequest, psInfo->pszMainTableName); + pszRequest = msStringConcatenate(pszRequest, "')"); + CPLPushErrorHandler(CPLQuietErrorHandler); + OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL ); + CPLPopErrorHandler(); + msFree(pszRequest); + + if( hLayer ) + { + OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer); + psInfo->bIsOKForSQLCompose = (hFeature != NULL); + if( hFeature ) + { + psInfo->pszSelect = msStrdup(psInfo->pszLayerDef); + msFree(psInfo->pszSpatialFilterTableName); + psInfo->pszSpatialFilterTableName = msStrdup( OGR_F_GetFieldAsString( hFeature, 0 ) ); + CPLFree( psInfo->pszSpatialFilterGeometryColumn ); + psInfo->pszSpatialFilterGeometryColumn = msStrdup( OGR_F_GetFieldAsString( hFeature, 1 ) ); + psInfo->pszRowId = msStrdup( OGR_F_GetFieldAsString( hFeature, 2 ) ); + OGR_F_Destroy(hFeature); + } + OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer ); + } + } + } + } + } + else + { + psInfo->bIsOKForSQLCompose = false; + + char* pszRequest = NULL; + pszRequest = msStringConcatenate(pszRequest, + "SELECT * FROM sqlite_master WHERE type = 'table' AND name = lower('"); + pszRequest = msStringConcatenate(pszRequest, OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer))); + pszRequest = msStringConcatenate(pszRequest, "')"); + OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL ); + msFree(pszRequest); + + if( hLayer ) + { + OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer); + psInfo->bIsOKForSQLCompose = (hFeature != NULL); + if( hFeature ) + OGR_F_Destroy(hFeature); + OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer ); + } + if( psInfo->bIsOKForSQLCompose ) + { + psInfo->pszMainTableName = msStrdup(OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer))); + psInfo->pszSpatialFilterTableName = msStrdup(psInfo->pszMainTableName); + psInfo->pszSpatialFilterGeometryColumn = msStrdup( OGR_L_GetGeometryColumn(psInfo->hLayer) ); + } + else + { + // Test if it is a spatial view + pszRequest = msStringConcatenate(NULL, + "SELECT f_table_name, f_geometry_column, view_rowid FROM views_geometry_columns WHERE view_name = lower('"); + pszRequest = msStringConcatenate(pszRequest, OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer))); + pszRequest = msStringConcatenate(pszRequest, "')"); + CPLPushErrorHandler(CPLQuietErrorHandler); + OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL ); + CPLPopErrorHandler(); + msFree(pszRequest); + + if( hLayer ) + { + OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer); + psInfo->bIsOKForSQLCompose = (hFeature != NULL); + if( hFeature ) + { + psInfo->pszMainTableName = msStrdup(OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer))); + psInfo->pszSpatialFilterTableName = msStrdup( OGR_F_GetFieldAsString( hFeature, 0 ) ); + psInfo->pszSpatialFilterGeometryColumn = msStrdup( OGR_F_GetFieldAsString( hFeature, 1 ) ); + psInfo->pszRowId = msStrdup( OGR_F_GetFieldAsString( hFeature, 2 ) ); + OGR_F_Destroy(hFeature); + } + OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer ); + } + } + } + + // in the case we cannot handle the native string, go back to the client + // side evaluation by unsetting it. + if( !psInfo->bIsOKForSQLCompose && psInfo->dialect != NULL ) + { + msDebug("msOGRFileOpen(): Falling back to MapServer only evaluation\n"); + psInfo->dialect = NULL; + } + + // Check if spatial index has been disabled (testing purposes) + if (msLayerGetProcessingKey(layer, "USE_SPATIAL_INDEX") != NULL && + !CSLTestBoolean(msLayerGetProcessingKey(layer, "USE_SPATIAL_INDEX")) ) + { + msDebug("msOGRFileOpen(): Layer %s has spatial index disabled by processing option\n", + pszLayerDef); + } + // Test if spatial index is available + else if( psInfo->dialect != NULL ) + { + char* pszRequest = NULL; + pszRequest = msStringConcatenate(pszRequest, + "SELECT * FROM sqlite_master WHERE type = 'table' AND name = 'idx_"); + pszRequest = msStringConcatenate(pszRequest, + psInfo->pszSpatialFilterTableName); + pszRequest = msStringConcatenate(pszRequest, "_"); + pszRequest = msStringConcatenate(pszRequest, + OGR_L_GetGeometryColumn(psInfo->hLayer)); + pszRequest = msStringConcatenate(pszRequest, "'"); + + psInfo->bHasSpatialIndex = false; + //msDebug("msOGRFileOpen(): %s", pszRequest); + + OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL ); + if( hLayer ) + { + OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer); + if( hFeature ) + { + psInfo->bHasSpatialIndex = true; + OGR_F_Destroy(hFeature); + } + OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer ); + } + msFree(pszRequest); + pszRequest = NULL; + + if( !psInfo->bHasSpatialIndex ) + { + msDebug("msOGRFileOpen(): Layer %s has no spatial index table\n", + pszLayerDef); + } + else + { + pszRequest = msStringConcatenate(pszRequest, + "SELECT * FROM geometry_columns WHERE f_table_name = lower('"); + pszRequest = msStringConcatenate(pszRequest, + psInfo->pszSpatialFilterTableName); + pszRequest = msStringConcatenate(pszRequest, "') AND f_geometry_column = lower('"); + pszRequest = msStringConcatenate(pszRequest, + psInfo->pszSpatialFilterGeometryColumn); + pszRequest = msStringConcatenate(pszRequest, "') AND spatial_index_enabled = 1"); + + psInfo->bHasSpatialIndex = false; + + OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL ); + if( hLayer ) + { + OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer); + if( hFeature ) + { + psInfo->bHasSpatialIndex = true; + OGR_F_Destroy(hFeature); + } + OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer ); + } + msFree(pszRequest); + pszRequest = NULL; + + if( !psInfo->bHasSpatialIndex ) + { + msDebug("msOGRFileOpen(): Layer %s has spatial index disabled\n", + pszLayerDef); + } + else + { + msDebug("msOGRFileOpen(): Layer %s has spatial index enabled\n", + pszLayerDef); + + psInfo->pszTablePrefix = msStrdup( psInfo->pszMainTableName ); + } + } + } + + psInfo->bPaging = (psInfo->dialect != NULL); +} + /************************************************************************/ /* msOGRCloseConnection() */ /* */ @@ -1313,6 +1695,14 @@ static int msOGRFileClose(layerObj *layer, msOGRFileInfo *psInfo ) // Free current tile if there is one. if( psInfo->poCurTile != NULL ) msOGRFileClose( layer, psInfo->poCurTile ); + + msFree(psInfo->pszSelect); + msFree(psInfo->pszSpatialFilterTableName); + msFree(psInfo->pszSpatialFilterGeometryColumn); + msFree(psInfo->pszMainTableName); + msFree(psInfo->pszRowId); + msFree(psInfo->pszTablePrefix); + msFree(psInfo->pszWHERE); CPLFree(psInfo); @@ -1327,7 +1717,7 @@ static char *msOGREscapeSQLParam(layerObj *layer, const char *pszString) { #ifdef USE_OGR char* pszEscapedStr =NULL; - if(layer && pszString && strlen(pszString) > 0) { + if(layer && pszString) { char* pszEscapedOGRStr = CPLEscapeString(pszString, strlen(pszString), CPLES_SQL ); pszEscapedStr = msStrdup(pszEscapedOGRStr); @@ -1348,155 +1738,415 @@ static char *msOGREscapeSQLParam(layerObj *layer, const char *pszString) #ifdef USE_OGR -#if 0 /*left over code from filter translation development */ -/********************************************************************** - * msOGRTranslateMsExpressionToOGRSQL() - * - * Tries to translate a mapserver expression to OGR SQL, and also - * try to extract spatial filter - **********************************************************************/ -static char* msOGRTranslateMsExpressionToOGRSQL(layerObj* layer, - expressionObj* psFilter, - rectObj* psRect) -{ - char* msSQLExpression = NULL; - rectObj sBBOX; - int sBBOXValid = MS_FALSE; - tokenListNodeObjPtr node = NULL; - char *stresc = NULL; - char *snippet = NULL; - const char* strtmpl = NULL; - int bIsIntersectRectangle = MS_FALSE; +// http://www.sqlite.org/lang_expr.html +// http://www.gaia-gis.it/gaia-sins/spatialite-sql-4.3.0.html - node = psFilter->tokens; - while (node != NULL) { +static char* msOGRGetQuotedItem(layerObj* layer, const char* pszItem ) +{ + msOGRFileInfo *psInfo = (msOGRFileInfo *)layer->layerinfo; + char* ret = NULL; + char* escapedItem = msLayerEscapePropertyName(layer, pszItem); + if( psInfo->pszTablePrefix) + { + char* escapedTable = msLayerEscapePropertyName(layer, psInfo->pszTablePrefix); + ret = msStringConcatenate(ret, "\""); + ret = msStringConcatenate(ret, escapedTable); + ret = msStringConcatenate(ret, "\".\""); + ret = msStringConcatenate(ret, escapedItem); + ret = msStringConcatenate(ret, "\""); + msFree(escapedTable); + } + else + { + ret = msStringConcatenate(ret, "\""); + ret = msStringConcatenate(ret, escapedItem); + ret = msStringConcatenate(ret, "\""); + } + msFree(escapedItem); + return ret; +} - switch(node->token) { +static +char *msOGRGetToken(layerObj* layer, tokenListNodeObjPtr *node) { + msOGRFileInfo *info = (msOGRFileInfo *)layer->layerinfo; + tokenListNodeObjPtr n = *node; + if (!n) return NULL; + char *out = NULL; + size_t nOutSize; + + switch(n->token) { + case MS_TOKEN_LOGICAL_AND: + out = msStrdup(" AND "); + break; + case MS_TOKEN_LOGICAL_OR: + out = msStrdup(" OR "); + break; + case MS_TOKEN_LOGICAL_NOT: + out = msStrdup(" NOT "); + break; + case MS_TOKEN_LITERAL_NUMBER: + nOutSize = 80; + out = (char *)msSmallMalloc(nOutSize); + snprintf(out, nOutSize, "%lf", n->tokenval.dblval); + break; + case MS_TOKEN_LITERAL_STRING: { + char *stresc = msOGREscapeSQLParam(layer, n->tokenval.strval); + nOutSize = strlen(stresc)+3; + out = (char *)msSmallMalloc(nOutSize); + snprintf(out, nOutSize, "'%s'", stresc); + msFree(stresc); + break; + } + case MS_TOKEN_LITERAL_TIME: + // seems to require METADATA gml_types => auto + nOutSize = 80; + out = (char *)msSmallMalloc(nOutSize); +#if 0 + // FIXME? or perhaps just remove me. tm_zone is not supported on Windows, and not used anywhere else in the code base + if (n->tokenval.tmval.tm_zone) + snprintf(out, nOutSize, "'%d-%02d-%02dT%02d:%02d:%02d%s'", + n->tokenval.tmval.tm_year+1900, n->tokenval.tmval.tm_mon+1, n->tokenval.tmval.tm_mday, + n->tokenval.tmval.tm_hour, n->tokenval.tmval.tm_min, n->tokenval.tmval.tm_sec, + n->tokenval.tmval.tm_zone); + else +#endif + snprintf(out, nOutSize, "'%d-%02d-%02dT%02d:%02d:%02d'", + n->tokenval.tmval.tm_year+1900, n->tokenval.tmval.tm_mon+1, n->tokenval.tmval.tm_mday, + n->tokenval.tmval.tm_hour, n->tokenval.tmval.tm_min, n->tokenval.tmval.tm_sec); + break; + case MS_TOKEN_LITERAL_SHAPE: { + // assumed to be in right srs after FLTGetSpatialComparisonCommonExpression + char *wkt = msShapeToWKT(n->tokenval.shpval); + char *stresc = msOGRGetQuotedItem(layer, OGR_L_GetGeometryColumn(info->hLayer)); // which geom field?? + nOutSize = strlen(wkt)+strlen(stresc)+35; + out = (char *)msSmallMalloc(nOutSize); + snprintf(out, nOutSize, "ST_GeomFromText('%s',ST_SRID(%s))", wkt, stresc); + msFree(wkt); + msFree(stresc); + break; + } + case MS_TOKEN_LITERAL_BOOLEAN: + out = msStrdup(n->tokenval.dblval == 0 ? "FALSE" : "TRUE"); + break; + case MS_TOKEN_COMPARISON_EQ: + if(n->next != NULL && n->next->token == MS_TOKEN_LITERAL_STRING && + strcmp(n->next->tokenval.strval, "_MAPSERVER_NULL_") == 0 ) + { + out = msStrdup(" IS NULL"); + n = n->next; + break; + } - /* literal tokens */ + out = msStrdup(" = "); + break; + case MS_TOKEN_COMPARISON_NE: + out = msStrdup(" != "); + break; + case MS_TOKEN_COMPARISON_GT: + out = msStrdup(" > "); + break; + case MS_TOKEN_COMPARISON_LT: + out = msStrdup(" < "); + break; + case MS_TOKEN_COMPARISON_LE: + out = msStrdup(" <= "); + break; + case MS_TOKEN_COMPARISON_GE: + out = msStrdup(" >= "); + break; + case MS_TOKEN_COMPARISON_IEQ: + out = msStrdup(" = "); + break; + case MS_TOKEN_COMPARISON_IN: + out = msStrdup(" IN "); + break; + // the origin may be mapfile (complex regexes, layer->map.query.filter.string == NULL, regex may have //) or + // OGC Filter (simple patterns only, layer->map.query.filter.string != NULL) + case MS_TOKEN_COMPARISON_RE: + case MS_TOKEN_COMPARISON_IRE: + case MS_TOKEN_COMPARISON_LIKE: { + int case_sensitive = n->token == MS_TOKEN_COMPARISON_RE || n->token == MS_TOKEN_COMPARISON_LIKE; + // in PostgreSQL and OGR: LIKE (case sensitive) and ILIKE (case insensitive) + // in SQLite: LIKE (case insensitive) and GLOB (case sensitive) + const char *op = case_sensitive ? "LIKE" : "ILIKE"; + char wild_any = '%'; + char wild_one = '_'; + + if (EQUAL(info->dialect, "Spatialite") || EQUAL(info->dialect, "GPKG")) { + if (case_sensitive) { + op = "GLOB"; + wild_any = '*'; + wild_one = '?'; + } else { + op = "LIKE"; + } + } - case MS_TOKEN_LITERAL_NUMBER: - snippet = (char *) msSmallMalloc(strlen(strtmpl) + 16); - sprintf(snippet, "%lf", node->tokenval.dblval); - msSQLExpression = msStringConcatenate(msSQLExpression, snippet); - msFree(snippet); - break; - case MS_TOKEN_LITERAL_STRING: - stresc = msOGREscapeSQLParam(layer, node->tokenval.strval); - snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(stresc)); - sprintf(snippet, "'%s'", stresc); - msSQLExpression = msStringConcatenate(msSQLExpression, snippet); - msFree(snippet); - msFree(stresc); - break; + n = n->next; + if (n->token != MS_TOKEN_LITERAL_STRING) return NULL; - case MS_TOKEN_BINDING_DOUBLE: - case MS_TOKEN_BINDING_INTEGER: - case MS_TOKEN_BINDING_STRING: - if(node->token == MS_TOKEN_BINDING_STRING || node->next->token == MS_TOKEN_COMPARISON_RE || node->next->token == MS_TOKEN_COMPARISON_IRE) - strtmpl = "CAST(%s AS CHARACTER)"; /* explicit cast necessary for certain operators */ - else - strtmpl = "%s"; - stresc = msLayerEscapePropertyName(layer, node->tokenval.bindval.item); - snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(stresc)); - sprintf(snippet, strtmpl, stresc); - msSQLExpression = msStringConcatenate(msSQLExpression, snippet); - msFree(snippet); - msFree(stresc); - break; + char *regex = msStrdup(n->tokenval.strval); + int complex_regex = *n->tokenval.strval == '/'; // could be non-complex but that is soo corner case - /* spatial comparison tokens */ - case MS_TOKEN_COMPARISON_INTERSECTS: - { - shapeObj* shape; - if(node->next->token != '(') goto cleanup; - if(node->next->next->token != MS_TOKEN_BINDING_SHAPE) goto cleanup; - if(node->next->next->next->token != ',' ) goto cleanup; - if(node->next->next->next->next->token != MS_TOKEN_LITERAL_SHAPE ) goto cleanup; - if(node->next->next->next->next->next->token != ')' ) goto cleanup; - if(node->next->next->next->next->next->next->token != MS_TOKEN_COMPARISON_EQ ) goto cleanup; - if(node->next->next->next->next->next->next->next->token != MS_TOKEN_LITERAL_BOOLEAN ) goto cleanup; - if(node->next->next->next->next->next->next->next->tokenval.dblval != MS_TRUE) goto cleanup; - - shape = node->next->next->next->next->tokenval.shpval; - memcpy(&sBBOX, &(shape->bounds), sizeof(rectObj)); - sBBOXValid = TRUE; - - if( shape->type == MS_SHAPE_POLYGON && - shape->numlines == 1 && - shape->line[0].numpoints == 5 ) - { - if( shape->line[0].point[0].x == shape->line[0].point[1].x && - shape->line[0].point[0].y == shape->line[0].point[3].y && - shape->line[0].point[2].x == shape->line[0].point[3].x && - shape->line[0].point[1].y == shape->line[0].point[2].y && - shape->line[0].point[0].x == shape->line[0].point[4].x && - shape->line[0].point[0].y == shape->line[0].point[4].y ) - { - bIsIntersectRectangle = MS_TRUE; - } - } + // PostgreSQL has POSIX regexes, SQLite does not by default, OGR does not + if (complex_regex) { + if (!EQUAL(info->dialect, "PostgreSQL")) { + msFree(regex); + return NULL; + } + // remove // + regex++; + regex[strlen(regex) - 1] = '\0'; + if (case_sensitive) + op = "~"; + else + op = "~*"; + } - node = node->next->next->next->next->next->next->next; - if( node && node->next && node->next->token == MS_TOKEN_LOGICAL_AND ) - node = node->next; + char *re = (char *) msSmallMalloc(strlen(regex)+3); + size_t i = 0, j = 0; + re[j++] = '\''; + while (i < strlen(regex)) { + char c = regex[i]; + char c_next = regex[i+1]; + + if (c == '.' && c_next == '*') { + i++; + c = wild_any; + } + else if (c == '.') + c = wild_one; - break; + if (i == 0 && c == '^') { + i++; + continue; + } + + re[j++] = c; + i++; + + } + re[j++] = '\''; + re[j] = '\0'; + + nOutSize = 1 + strlen(op)+ 1 + strlen(re) + 1; + out = (char *)msSmallMalloc(nOutSize); + snprintf(out, nOutSize, " %s %s", op, re); + msFree(re); + msFree(regex); + break; + } + case MS_TOKEN_COMPARISON_INTERSECTS: + out = msStrdup("ST_Intersects"); + break; + case MS_TOKEN_COMPARISON_DISJOINT: + out = msStrdup("ST_Disjoint"); + break; + case MS_TOKEN_COMPARISON_TOUCHES: + out = msStrdup("ST_Touches"); + break; + case MS_TOKEN_COMPARISON_OVERLAPS: + out = msStrdup("ST_Overlaps"); + break; + case MS_TOKEN_COMPARISON_CROSSES: + out = msStrdup("ST_Crosses"); + break; + case MS_TOKEN_COMPARISON_WITHIN: + out = msStrdup("ST_Within"); + break; + case MS_TOKEN_COMPARISON_DWITHIN: + out = msStrdup("ST_Distance"); + break; + case MS_TOKEN_COMPARISON_BEYOND: + out = msStrdup("ST_Distance"); + break; + case MS_TOKEN_COMPARISON_CONTAINS: + out = msStrdup("ST_Contains"); + break; + case MS_TOKEN_COMPARISON_EQUALS: + out = msStrdup("ST_Equals"); + break; + case MS_TOKEN_FUNCTION_LENGTH: + out = msStrdup("ST_Length"); + break; + case MS_TOKEN_FUNCTION_AREA: + out = msStrdup("ST_Area"); + break; + case MS_TOKEN_BINDING_DOUBLE: { + char *stresc = msOGRGetQuotedItem(layer, n->tokenval.bindval.item); + nOutSize = strlen(stresc)+ + 30; + out = (char *)msSmallMalloc(nOutSize); + + char md_item_name[256]; + snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", + n->tokenval.bindval.item ); + const char* type = msLookupHashTable(&(layer->metadata), md_item_name); + // Do not cast if the variable is of the appropriate type as it can + // prevent using database indexes, such as for SQlite + if( type != NULL && (EQUAL(type, "Integer") || + EQUAL(type, "Long") || + EQUAL(type, "Real")) ) + { + snprintf(out, nOutSize, "%s", stresc); + } + else + { + const char *SQLtype = "float(16)"; + if (EQUAL(info->dialect, "Spatialite") || EQUAL(info->dialect, "GPKG")) + SQLtype = "REAL"; + else if (EQUAL(info->dialect, "PostgreSQL")) + SQLtype = "double precision"; + snprintf(out, nOutSize, "CAST(%s AS %s)", stresc, SQLtype); + } + msFree(stresc); + break; + } + case MS_TOKEN_BINDING_INTEGER: { + char *stresc = msOGRGetQuotedItem(layer, n->tokenval.bindval.item); + nOutSize = strlen(stresc)+ 20; + out = (char *)msSmallMalloc(nOutSize); + + char md_item_name[256]; + snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", + n->tokenval.bindval.item ); + const char* type = msLookupHashTable(&(layer->metadata), md_item_name); + // Do not cast if the variable is of the appropriate type as it can + // prevent using database indexes, such as for SQlite + if( type != NULL && (EQUAL(type, "Integer") || + EQUAL(type, "Long") || + EQUAL(type, "Real")) ) + { + snprintf(out, nOutSize, "%s", stresc); + } + else + { + snprintf(out, nOutSize, "CAST(%s AS integer)", stresc); + } + msFree(stresc); + break; + } + case MS_TOKEN_BINDING_STRING: { + char *stresc = msOGRGetQuotedItem(layer, n->tokenval.bindval.item); + nOutSize = strlen(stresc) + 30; + out = (char *)msSmallMalloc(nOutSize); + + char md_item_name[256]; + snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", + n->tokenval.bindval.item ); + const char* type = msLookupHashTable(&(layer->metadata), md_item_name); + // Do not cast if the variable is of the appropriate type as it can + // prevent using database indexes, such as for SQlite + if( type != NULL && EQUAL(type, "Character") ) + { + snprintf(out, nOutSize, "%s", stresc); + } + else + { + snprintf(out, nOutSize, "CAST(%s AS text)", stresc); } + msFree(stresc); + break; + } + case MS_TOKEN_BINDING_TIME: { + // won't get here unless col is parsed as time and they are not + char *stresc = msOGRGetQuotedItem(layer, n->tokenval.bindval.item); + nOutSize = strlen(stresc)+ 10; + out = (char *)msSmallMalloc(nOutSize); + snprintf(out, nOutSize, "%s", stresc); + msFree(stresc); + break; + } + case MS_TOKEN_BINDING_SHAPE: { + char *stresc = msOGRGetQuotedItem(layer, OGR_L_GetGeometryColumn(info->hLayer)); // which geom field?? + nOutSize = strlen(stresc)+ 10; + out = (char *)msSmallMalloc(nOutSize); + snprintf(out, nOutSize, "%s", stresc); + msFree(stresc); + break; + } - case MS_TOKEN_COMPARISON_EQ: - case MS_TOKEN_COMPARISON_NE: - case MS_TOKEN_COMPARISON_GT: - case MS_TOKEN_COMPARISON_GE: - case MS_TOKEN_COMPARISON_LT: - case MS_TOKEN_COMPARISON_LE: - case MS_TOKEN_LOGICAL_AND: - case MS_TOKEN_LOGICAL_NOT: - case MS_TOKEN_LOGICAL_OR: - case '(': - case ')': - if( node->token == MS_TOKEN_LOGICAL_AND && node->next && - node->next->token == MS_TOKEN_COMPARISON_INTERSECTS ) - node = node->next; - else - msSQLExpression = msStringConcatenate(msSQLExpression, msExpressionTokenToString(node->token)); - break; + // unhandled below until default + + case MS_TOKEN_FUNCTION_TOSTRING: + case MS_TOKEN_FUNCTION_COMMIFY: + case MS_TOKEN_FUNCTION_ROUND: + case MS_TOKEN_FUNCTION_FROMTEXT: + case MS_TOKEN_FUNCTION_BUFFER: + case MS_TOKEN_FUNCTION_DIFFERENCE: + case MS_TOKEN_FUNCTION_SIMPLIFY: + case MS_TOKEN_FUNCTION_SIMPLIFYPT: + case MS_TOKEN_FUNCTION_GENERALIZE: + case MS_TOKEN_FUNCTION_SMOOTHSIA: + case MS_TOKEN_FUNCTION_JAVASCRIPT: + case MS_TOKEN_FUNCTION_UPPER: + case MS_TOKEN_FUNCTION_LOWER: + case MS_TOKEN_FUNCTION_INITCAP: + case MS_TOKEN_FUNCTION_FIRSTCAP: + case MS_TOKEN_BINDING_MAP_CELLSIZE: + case MS_TOKEN_BINDING_DATA_CELLSIZE: + case MS_PARSE_TYPE_BOOLEAN: + case MS_PARSE_TYPE_STRING: + case MS_PARSE_TYPE_SHAPE: + break; - default: - goto cleanup; - break; + default: + if (n->token < 128) { + char c = n->token; + out = (char *)msSmallMalloc(2); + sprintf(out, "%c", c); } + break; + } - node = node->next; - } - - if( !sBBOXValid || bIsIntersectRectangle ) - { - /* We can translate completely the filter as a OGR expression, */ - /* so no need for msEvalExpression() to do more work */ - - if (layer->debug >= MS_DEBUGLEVEL_VVV) - msDebug("msOGRTranslateMsExpressionToOGRSQL: filter can be evaluated completely on OGR side\n"); + n = n->next; + *node = n; + return out; +} - msFree( layer->filter.native_string ); - layer->filter.native_string = msStrdup(msSQLExpression); - } - - if( sBBOXValid ) - { - psRect->minx = MS_MAX(psRect->minx, sBBOX.minx); - psRect->miny = MS_MAX(psRect->miny, sBBOX.miny); - psRect->maxx = MS_MIN(psRect->maxx, sBBOX.maxx); - psRect->maxy = MS_MAX(psRect->maxy, sBBOX.maxy); +/* + * msOGRLayerBuildSQLOrderBy() + * + * Returns the content of a SQL ORDER BY clause from the sortBy member of + * the layer. The string does not contain the "ORDER BY" keywords itself. + */ +static char* msOGRLayerBuildSQLOrderBy(layerObj *layer, msOGRFileInfo *psInfo) +{ + char* strOrderBy = NULL; + if( layer->sortBy.nProperties > 0 ) { + int i; + for(i=0;isortBy.nProperties;i++) { + if( i > 0 ) + strOrderBy = msStringConcatenate(strOrderBy, ", "); + char* escapedItem = msLayerEscapePropertyName(layer, layer->sortBy.properties[i].item); + if( psInfo->pszTablePrefix) + { + char* escapedTable = msLayerEscapePropertyName(layer, psInfo->pszTablePrefix); + strOrderBy = msStringConcatenate(strOrderBy, "\""); + strOrderBy = msStringConcatenate(strOrderBy, escapedTable); + strOrderBy = msStringConcatenate(strOrderBy, "\".\""); + strOrderBy = msStringConcatenate(strOrderBy, escapedItem); + strOrderBy = msStringConcatenate(strOrderBy, "\""); + msFree(escapedTable); + } + else + { +#if GDAL_VERSION_MAJOR < 2 + // Old GDAL don't like quoted identifiers in ORDER BY + strOrderBy = msStringConcatenate(strOrderBy, + layer->sortBy.properties[i].item); +#else + strOrderBy = msStringConcatenate(strOrderBy, "\""); + strOrderBy = msStringConcatenate(strOrderBy, escapedItem); + strOrderBy = msStringConcatenate(strOrderBy, "\""); +#endif + } + msFree(escapedItem); + if( layer->sortBy.properties[i].sortOrder == SORT_DESC ) + strOrderBy = msStringConcatenate(strOrderBy, " DESC"); + } } - - return msSQLExpression; - -cleanup: - msFree(msSQLExpression); - return NULL; + return strOrderBy; } -#endif //0 /********************************************************************** * msOGRFileWhichShapes() @@ -1508,178 +2158,459 @@ static char* msOGRTranslateMsExpressionToOGRSQL(layerObj* layer, **********************************************************************/ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *psInfo) { - if (psInfo == NULL || psInfo->hLayer == NULL) { - msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRFileWhichShapes()"); - return(MS_FAILURE); - } - - char *pszOGRFilter = NULL; - - /* - ** Build the OGR filter from two potential sources: - ** 1) the NATIVE_FILTER processing option - ** 2) a translated MapServer layer->filter (stored in layer->native_string) - */ - if(msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL) { - pszOGRFilter = msStringConcatenate(pszOGRFilter, "("); - pszOGRFilter = msStringConcatenate(pszOGRFilter, msLayerGetProcessingKey(layer, "NATIVE_FILTER")); - pszOGRFilter = msStringConcatenate(pszOGRFilter, ")"); - if(layer->filter.native_string) { - pszOGRFilter = msStringConcatenate(pszOGRFilter, "AND ("); - pszOGRFilter = msStringConcatenate(pszOGRFilter, layer->filter.native_string); - pszOGRFilter = msStringConcatenate(pszOGRFilter, ")"); - } - } else if(layer->filter.native_string) { - pszOGRFilter = msStringConcatenate(pszOGRFilter, "("); - pszOGRFilter = msStringConcatenate(pszOGRFilter, layer->filter.native_string); - pszOGRFilter = msStringConcatenate(pszOGRFilter, ")"); - } - - /* apply sortBy */ - if( layer->sortBy.nProperties > 0 ) { - char* strOrderBy; - char* pszLayerDef = NULL; + // rect is from BBOX parameter in query (In lieu of a FEATUREID or FILTER) or mapfile somehow + if (psInfo == NULL || psInfo->hLayer == NULL) { + msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRFileWhichShapes()"); + return(MS_FAILURE); + } - strOrderBy = msLayerBuildSQLOrderBy(layer); + char *select = (psInfo->pszSelect) ? msStrdup(psInfo->pszSelect) : NULL; + const rectObj rectInvalid = MS_INIT_INVALID_RECT; + bool bIsValidRect = memcmp(&rect, &rectInvalid, sizeof(rect)) != 0; - if( psInfo->nLayerIndex == -1 ) { - pszLayerDef = msStrdup(psInfo->pszLayerDef); - if( strcasestr(psInfo->pszLayerDef, " ORDER BY ") == NULL ) - pszLayerDef = msStringConcatenate(pszLayerDef, " ORDER BY "); - else - pszLayerDef = msStringConcatenate(pszLayerDef, ", "); - } else { - const char* pszGeometryColumn; - int i; - pszLayerDef = msStringConcatenate(pszLayerDef, "SELECT "); - for(i = 0; i < layer->numitems; i++) { - if( i > 0 ) - pszLayerDef = msStringConcatenate(pszLayerDef, ", "); - pszLayerDef = msStringConcatenate(pszLayerDef, "\""); - pszLayerDef = msStringConcatenate(pszLayerDef, layer->items[i]); - pszLayerDef = msStringConcatenate(pszLayerDef, "\""); - } + // we'll go strictly two possible ways: + // 1) GetLayer + SetFilter + // 2) ExecuteSQL (psInfo->hLayer is an SQL result OR sortBy was requested OR have native_string + // and start from the second - pszLayerDef = msStringConcatenate(pszLayerDef, ", "); - pszGeometryColumn = OGR_L_GetGeometryColumn(psInfo->hLayer); - if( pszGeometryColumn != NULL && pszGeometryColumn[0] != '\0' ) { - pszLayerDef = msStringConcatenate(pszLayerDef, "\""); - pszLayerDef = msStringConcatenate(pszLayerDef, pszGeometryColumn); - pszLayerDef = msStringConcatenate(pszLayerDef, "\""); - } else { - /* Add ", *" so that we still have an hope to get the geometry */ - pszLayerDef = msStringConcatenate(pszLayerDef, "*"); - } - pszLayerDef = msStringConcatenate(pszLayerDef, " FROM \""); - pszLayerDef = msStringConcatenate(pszLayerDef, OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer))); - pszLayerDef = msStringConcatenate(pszLayerDef, "\""); - if( pszOGRFilter != NULL ) { - pszLayerDef = msStringConcatenate(pszLayerDef, " WHERE "); - pszLayerDef = msStringConcatenate(pszLayerDef, pszOGRFilter); - msFree(pszOGRFilter); - pszOGRFilter = NULL; - } - pszLayerDef = msStringConcatenate(pszLayerDef, " ORDER BY "); - } + if ( psInfo->bIsOKForSQLCompose && (psInfo->nLayerIndex == -1 || + layer->sortBy.nProperties > 0 || + layer->filter.native_string || + (psInfo->bPaging && layer->maxfeatures > 0)) ) { - pszLayerDef = msStringConcatenate(pszLayerDef, strOrderBy); - msFree(strOrderBy); - strOrderBy = NULL; + const bool bHasGeometry = + OGR_L_GetGeomType( psInfo->hLayer ) != wkbNone; - if( layer->debug ) - msDebug("msOGRFileWhichShapes: SQL = %s.\n", pszLayerDef); + if( psInfo->nLayerIndex == -1 && select == NULL ) { + select = msStrdup(psInfo->pszLayerDef); + /* If nLayerIndex == -1 then the layer is an SQL result ... free it */ + OGR_DS_ReleaseResultSet( psInfo->hDS, psInfo->hLayer ); + psInfo->hLayer = NULL; + } + else if( select == NULL ) { + const char* pszGeometryColumn; + int i; + select = msStringConcatenate(select, "SELECT "); + for(i = 0; i < layer->numitems; i++) { + if( i > 0 ) + select = msStringConcatenate(select, ", "); + char* escaped = msOGRGetQuotedItem(layer, layer->items[i]); + select = msStringConcatenate(select, escaped); + msFree(escaped); + if( psInfo->pszTablePrefix ) + { + select = msStringConcatenate(select, " AS \""); + escaped = msLayerEscapePropertyName(layer, layer->items[i]); + select = msStringConcatenate(select, escaped); + msFree(escaped); + select = msStringConcatenate(select, "\""); + } + } + if( layer->numitems > 0 ) + select = msStringConcatenate(select, ", "); + pszGeometryColumn = OGR_L_GetGeometryColumn(psInfo->hLayer); + if( pszGeometryColumn != NULL && pszGeometryColumn[0] != '\0' ) { + char* escaped = msOGRGetQuotedItem(layer, pszGeometryColumn); + select = msStringConcatenate(select, escaped); + msFree(escaped); + if( psInfo->pszTablePrefix ) + { + select = msStringConcatenate(select, " AS \""); + escaped = msLayerEscapePropertyName(layer, pszGeometryColumn); + select = msStringConcatenate(select, escaped); + msFree(escaped); + select = msStringConcatenate(select, "\""); + } + } else { + /* Add ", *" so that we still have an hope to get the geometry */ + if( psInfo->pszTablePrefix ) + { + select = msStringConcatenate(select, "\""); + char* escaped = msLayerEscapePropertyName(layer, psInfo->pszTablePrefix); + select = msStringConcatenate(select, escaped); + msFree(escaped); + select = msStringConcatenate(select, "\"."); + } + select = msStringConcatenate(select, "*"); + } + select = msStringConcatenate(select, " FROM "); + if( psInfo->nLayerIndex == -1 ) + { + select = msStringConcatenate(select, "("); + select = msStringConcatenate(select, psInfo->pszLayerDef); + select = msStringConcatenate(select, ") MSSUBSELECT"); + } + else + { + select = msStringConcatenate(select, "\""); + char* escaped = msLayerEscapePropertyName(layer, OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer))); + select = msStringConcatenate(select, escaped); + msFree(escaped); + select = msStringConcatenate(select, "\""); + } + } - /* If nLayerIndex == -1 then the layer is an SQL result ... free it */ - if( psInfo->nLayerIndex == -1 ) - OGR_DS_ReleaseResultSet( psInfo->hDS, psInfo->hLayer ); - psInfo->nLayerIndex = -1; + char *filter = NULL; + if (msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL) { + filter = msStringConcatenate(filter, "("); + filter = msStringConcatenate(filter, msLayerGetProcessingKey(layer, "NATIVE_FILTER")); + filter = msStringConcatenate(filter, ")"); + } - ACQUIRE_OGR_LOCK; - psInfo->hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszLayerDef, NULL, NULL ); - RELEASE_OGR_LOCK; - if( psInfo->hLayer == NULL ) { - msSetError(MS_OGRERR, "ExecuteSQL(%s) failed.\n%s", "msOGRFileWhichShapes()", pszLayerDef, CPLGetLastErrorMsg()); - msFree(pszLayerDef); - msFree(pszOGRFilter); - return MS_FAILURE; - } - msFree(pszLayerDef); - } /* end sort-by */ + /* ------------------------------------------------------------------ + * Set Spatial filter... this may result in no features being returned + * if layer does not overlap current view. + * + * __TODO__ We should return MS_DONE if no shape overlaps the selected + * region and matches the layer's FILTER expression, but there is currently + * no _efficient_ way to do that with OGR. + * ------------------------------------------------------------------ */ + if (psInfo->rect_is_defined) { + rect.minx = MAX(psInfo->rect.minx, rect.minx); + rect.miny = MAX(psInfo->rect.miny, rect.miny); + rect.maxx = MIN(psInfo->rect.maxx, rect.maxx); + rect.maxy = MIN(psInfo->rect.maxy, rect.maxy); + bIsValidRect = true; + } + psInfo->rect = rect; + bool bSpatialiteOrGPKGAddOrderByFID = false; - /* ------------------------------------------------------------------ - * Set Spatial filter... this may result in no features being returned - * if layer does not overlap current view. - * - * __TODO__ We should return MS_DONE if no shape overlaps the selected - * region and matches the layer's FILTER expression, but there is currently - * no _efficient_ way to do that with OGR. - * ------------------------------------------------------------------ */ - ACQUIRE_OGR_LOCK; + if( psInfo->dialect && psInfo->pszMainTableName != NULL && + ( (EQUAL(psInfo->dialect, "Spatialite") && psInfo->bHasSpatialIndex) + || EQUAL(psInfo->dialect, "GPKG") ) && + bIsValidRect ) + { + select = msStringConcatenate(select, " JOIN "); + + char szSpatialIndexName[256]; + snprintf( szSpatialIndexName, sizeof(szSpatialIndexName), + "%s_%s_%s", + EQUAL(psInfo->dialect, "Spatialite") ? "idx" : "rtree", + psInfo->pszSpatialFilterTableName, + psInfo->pszSpatialFilterGeometryColumn ); + char* pszEscapedSpatialIndexName = msLayerEscapePropertyName( + layer, szSpatialIndexName); + select = msStringConcatenate(select, "\""); + select = msStringConcatenate(select, pszEscapedSpatialIndexName); + msFree(pszEscapedSpatialIndexName); + select = msStringConcatenate(select, "\" ms_spat_idx ON \""); + char* pszEscapedMainTableName = msLayerEscapePropertyName( + layer, psInfo->pszMainTableName); + select = msStringConcatenate(select, pszEscapedMainTableName); + msFree(pszEscapedMainTableName); + select = msStringConcatenate(select, "\"."); + if( psInfo->pszRowId ) + { + char* pszEscapedRowId = msLayerEscapePropertyName( + layer, psInfo->pszRowId); + select = msStringConcatenate(select, "\""); + select = msStringConcatenate(select, pszEscapedRowId); + select = msStringConcatenate(select, "\""); + msFree(pszEscapedRowId); + } + else + select = msStringConcatenate(select, "ROWID"); + if( EQUAL(psInfo->dialect, "Spatialite") ) + select = msStringConcatenate(select, " = ms_spat_idx.pkid AND "); + else + select = msStringConcatenate(select, " = ms_spat_idx.id AND "); - if (rect.minx == rect.maxx && rect.miny == rect.maxy) { - OGRGeometryH hSpatialFilterPoint = OGR_G_CreateGeometry( wkbPoint ); + char szCond[256]; + if( EQUAL(psInfo->dialect, "Spatialite") ) + { + snprintf(szCond, sizeof(szCond), + "ms_spat_idx.xmin <= %.15g AND ms_spat_idx.xmax >= %.15g AND " + "ms_spat_idx.ymin <= %.15g AND ms_spat_idx.ymax >= %.15g", + rect.maxx, rect.minx, rect.maxy, rect.miny); + } + else + { + snprintf(szCond, sizeof(szCond), + "ms_spat_idx.minx <= %.15g AND ms_spat_idx.maxx >= %.15g AND " + "ms_spat_idx.miny <= %.15g AND ms_spat_idx.maxy >= %.15g", + rect.maxx, rect.minx, rect.maxy, rect.miny); + } + select = msStringConcatenate(select, szCond); - OGR_G_SetPoint_2D( hSpatialFilterPoint, 0, rect.minx, rect.miny ); - OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterPoint ); - OGR_G_DestroyGeometry( hSpatialFilterPoint ); - } else if (rect.minx == rect.maxx || rect.miny == rect.maxy) { - OGRGeometryH hSpatialFilterLine = OGR_G_CreateGeometry( wkbLineString ); + bSpatialiteOrGPKGAddOrderByFID = true; + } - OGR_G_AddPoint_2D( hSpatialFilterLine, rect.minx, rect.miny ); - OGR_G_AddPoint_2D( hSpatialFilterLine, rect.maxx, rect.maxy ); - OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterLine ); - OGR_G_DestroyGeometry( hSpatialFilterLine ); - } else { - OGRGeometryH hSpatialFilterPolygon = OGR_G_CreateGeometry( wkbPolygon ); - OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing ); + const char *sql = layer->filter.native_string; + if (psInfo->dialect && sql && *sql != '\0' && + (EQUAL(psInfo->dialect, "Spatialite") || + EQUAL(psInfo->dialect, "GPKG") || + EQUAL(psInfo->dialect, "PostgreSQL")) ) + { + if (filter) filter = msStringConcatenate(filter, " AND "); + filter = msStringConcatenate(filter, "("); + filter = msStringConcatenate(filter, sql); + filter = msStringConcatenate(filter, ")"); + } + else if( psInfo->pszWHERE ) + { + if (filter) filter = msStringConcatenate(filter, " AND "); + filter = msStringConcatenate(filter, "("); + filter = msStringConcatenate(filter, psInfo->pszWHERE); + filter = msStringConcatenate(filter, ")"); + } - OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny); - OGR_G_AddPoint_2D( hRing, rect.maxx, rect.miny); - OGR_G_AddPoint_2D( hRing, rect.maxx, rect.maxy); - OGR_G_AddPoint_2D( hRing, rect.minx, rect.maxy); - OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny); - OGR_G_AddGeometryDirectly( hSpatialFilterPolygon, hRing ); - OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterPolygon ); - OGR_G_DestroyGeometry( hSpatialFilterPolygon ); - } + bool bOffsetAlreadyAdded = false; + // use spatial index + if (psInfo->dialect && bIsValidRect ) { + if (EQUAL(psInfo->dialect, "PostgreSQL")) { + if (filter) filter = msStringConcatenate(filter, " AND"); + const char *col = OGR_L_GetGeometryColumn(psInfo->hLayer); // which geom field?? + filter = msStringConcatenate(filter, " (\""); + char* escaped = msLayerEscapePropertyName(layer, col); + filter = msStringConcatenate(filter, escaped); + msFree(escaped); + filter = msStringConcatenate(filter, "\" && ST_MakeEnvelope("); + char *points = (char *)msSmallMalloc(30*2*5); + snprintf(points, 30*4, "%lf,%lf,%lf,%lf", rect.minx, rect.miny, rect.maxx, rect.maxy); + filter = msStringConcatenate(filter, points); + msFree(points); + filter = msStringConcatenate(filter, "))"); + } + else if( psInfo->dialect && EQUAL(psInfo->dialect, "Spatialite") && + psInfo->pszMainTableName != NULL && !psInfo->bHasSpatialIndex ) + { + if (filter) filter = msStringConcatenate(filter, " AND"); + const char *col = OGR_L_GetGeometryColumn(psInfo->hLayer); // which geom field?? + filter = msStringConcatenate(filter, " MbrIntersects(\""); + char* escaped = msLayerEscapePropertyName(layer, col); + filter = msStringConcatenate(filter, escaped); + msFree(escaped); + filter = msStringConcatenate(filter, "\", BuildMbr("); + char *points = (char *)msSmallMalloc(30*2*5); + snprintf(points, 30*4, "%lf,%lf,%lf,%lf", rect.minx, rect.miny, rect.maxx, rect.maxy); + filter = msStringConcatenate(filter, points); + msFree(points); + filter = msStringConcatenate(filter, "))"); + } + } - psInfo->rect = rect; + /* get sortBy */ + char *sort = NULL; + if( layer->sortBy.nProperties > 0) { + + char *strOrderBy = msOGRLayerBuildSQLOrderBy(layer, psInfo); + if (strOrderBy) { + if( psInfo->nLayerIndex == -1 ) { + if( strcasestr(psInfo->pszLayerDef, " ORDER BY ") == NULL ) + sort = msStringConcatenate(sort, " ORDER BY "); + else + sort = msStringConcatenate(sort, ", "); + } else { + sort = msStringConcatenate(sort, " ORDER BY "); + } + sort = msStringConcatenate(sort, strOrderBy); + msFree(strOrderBy); + } + } - if (layer->debug >= MS_DEBUGLEVEL_VVV) - msDebug("msOGRFileWhichShapes: Setting spatial filter to %f %f %f %f\n", rect.minx, rect.miny, rect.maxx, rect.maxy ); + if( bSpatialiteOrGPKGAddOrderByFID ) + { + if( sort == NULL ) + sort = msStringConcatenate(NULL, " ORDER BY "); + else + sort = msStringConcatenate(sort, ", "); + char* pszEscapedMainTableName = msLayerEscapePropertyName( + layer, psInfo->pszMainTableName); + sort = msStringConcatenate(sort, "\""); + sort = msStringConcatenate(sort, pszEscapedMainTableName); + sort = msStringConcatenate(sort, "\"."); + msFree(pszEscapedMainTableName); + if( psInfo->pszRowId ) + { + char* pszEscapedRowId = msLayerEscapePropertyName( + layer, psInfo->pszRowId); + sort = msStringConcatenate(sort, "\""); + sort = msStringConcatenate(sort, pszEscapedRowId); + sort = msStringConcatenate(sort, "\""); + msFree(pszEscapedRowId); + } + else + sort = msStringConcatenate(sort, "ROWID"); + } - /* ------------------------------------------------------------------ - * Apply an attribute filter if we have one prefixed with a WHERE - * keyword in the filter string. Otherwise, ensure the attribute - * filter is clear. - * ------------------------------------------------------------------ */ - - if( pszOGRFilter != NULL ) { + // compose SQL + if (filter) { + select = msStringConcatenate(select, " WHERE "); + select = msStringConcatenate(select, filter); + msFree(filter); + } + if (sort) { + select = msStringConcatenate(select, " "); + select = msStringConcatenate(select, sort); + msFree(sort); + } - if (layer->debug >= MS_DEBUGLEVEL_VVV) - msDebug("msOGRFileWhichShapes: Setting attribute filter to %s\n", pszOGRFilter ); + if ( psInfo->bPaging && layer->maxfeatures >= 0 ) { + char szLimit[50]; + snprintf(szLimit, sizeof(szLimit), " LIMIT %d", layer->maxfeatures); + select = msStringConcatenate(select, szLimit); + } - CPLErrorReset(); - if( OGR_L_SetAttributeFilter( psInfo->hLayer, pszOGRFilter ) != OGRERR_NONE ) { - msSetError(MS_OGRERR, "SetAttributeFilter(%s) failed on layer %s.\n%s", "msOGRFileWhichShapes()", layer->filter.string+6, layer->name?layer->name:"(null)", CPLGetLastErrorMsg() ); - RELEASE_OGR_LOCK; - msFree(pszOGRFilter); - return MS_FAILURE; - } - msFree(pszOGRFilter); - } else - OGR_L_SetAttributeFilter( psInfo->hLayer, NULL ); + if ( !bOffsetAlreadyAdded && psInfo->bPaging && layer->startindex > 0 ) { + char szOffset[50]; + snprintf(szOffset, sizeof(szOffset), " OFFSET %d", layer->startindex); + select = msStringConcatenate(select, szOffset); + } - /* ------------------------------------------------------------------ - * Reset current feature pointer - * ------------------------------------------------------------------ */ - OGR_L_ResetReading( psInfo->hLayer ); - psInfo->last_record_index_read = -1; + if( layer->debug ) + msDebug("msOGRFileWhichShapes: SQL = %s.\n", select); - RELEASE_OGR_LOCK; + ACQUIRE_OGR_LOCK; + if( psInfo->nLayerIndex == -1 && psInfo->hLayer != NULL ) + { + OGR_DS_ReleaseResultSet( psInfo->hDS, psInfo->hLayer ); + } - return MS_SUCCESS; + OGRGeometryH hGeom = NULL; + if( psInfo->dialect == NULL && + bHasGeometry && bIsValidRect ) { + if (rect.minx == rect.maxx && rect.miny == rect.maxy) { + hGeom = OGR_G_CreateGeometry( wkbPoint ); + OGR_G_SetPoint_2D( hGeom, 0, rect.minx, rect.miny ); + } else if (rect.minx == rect.maxx || rect.miny == rect.maxy) { + hGeom = OGR_G_CreateGeometry( wkbLineString ); + OGR_G_AddPoint_2D( hGeom, rect.minx, rect.miny ); + OGR_G_AddPoint_2D( hGeom, rect.maxx, rect.maxy ); + } else { + hGeom = OGR_G_CreateGeometry( wkbPolygon ); + OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing ); + + OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny); + OGR_G_AddPoint_2D( hRing, rect.maxx, rect.miny); + OGR_G_AddPoint_2D( hRing, rect.maxx, rect.maxy); + OGR_G_AddPoint_2D( hRing, rect.minx, rect.maxy); + OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny); + OGR_G_AddGeometryDirectly( hGeom, hRing ); + } + + if (layer->debug >= MS_DEBUGLEVEL_VVV) + { + msDebug("msOGRFileWhichShapes: Setting spatial filter to %.15g %.15g %.15g %.15g\n", + rect.minx, rect.miny, rect.maxx, rect.maxy ); + } + } + + psInfo->hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, select, hGeom, NULL ); + psInfo->nLayerIndex = -1; + if( hGeom != NULL ) + OGR_G_DestroyGeometry(hGeom); + + if( psInfo->hLayer == NULL ) { + RELEASE_OGR_LOCK; + msSetError(MS_OGRERR, "ExecuteSQL() failed. Check logs.", "msOGRFileWhichShapes()"); + msDebug("ExecuteSQL(%s) failed.\n%s\n", select, CPLGetLastErrorMsg()); + msFree(select); + return MS_FAILURE; + } + + // Update itemindexes / layer->iteminfo + msOGRLayerInitItemInfo(layer); + } + else { + + // case of 1) GetLayer + SetFilter + + char *pszOGRFilter = NULL; + if (msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL) { + pszOGRFilter = msStringConcatenate(pszOGRFilter, "("); + pszOGRFilter = msStringConcatenate(pszOGRFilter, msLayerGetProcessingKey(layer, "NATIVE_FILTER")); + pszOGRFilter = msStringConcatenate(pszOGRFilter, ")"); + } + + if( psInfo->pszWHERE ) + { + if( pszOGRFilter ) + { + pszOGRFilter = msStringConcatenate(pszOGRFilter, " AND ("); + pszOGRFilter = msStringConcatenate(pszOGRFilter, psInfo->pszWHERE); + pszOGRFilter = msStringConcatenate(pszOGRFilter, ")"); + } + else + { + pszOGRFilter = msStringConcatenate(pszOGRFilter, psInfo->pszWHERE); + } + } + + ACQUIRE_OGR_LOCK; + + if( OGR_L_GetGeomType( psInfo->hLayer ) != wkbNone && bIsValidRect ) { + if (rect.minx == rect.maxx && rect.miny == rect.maxy) { + OGRGeometryH hSpatialFilterPoint = OGR_G_CreateGeometry( wkbPoint ); + + OGR_G_SetPoint_2D( hSpatialFilterPoint, 0, rect.minx, rect.miny ); + OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterPoint ); + OGR_G_DestroyGeometry( hSpatialFilterPoint ); + } else if (rect.minx == rect.maxx || rect.miny == rect.maxy) { + OGRGeometryH hSpatialFilterLine = OGR_G_CreateGeometry( wkbLineString ); + + OGR_G_AddPoint_2D( hSpatialFilterLine, rect.minx, rect.miny ); + OGR_G_AddPoint_2D( hSpatialFilterLine, rect.maxx, rect.maxy ); + OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterLine ); + OGR_G_DestroyGeometry( hSpatialFilterLine ); + } else { + OGRGeometryH hSpatialFilterPolygon = OGR_G_CreateGeometry( wkbPolygon ); + OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing ); + + OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny); + OGR_G_AddPoint_2D( hRing, rect.maxx, rect.miny); + OGR_G_AddPoint_2D( hRing, rect.maxx, rect.maxy); + OGR_G_AddPoint_2D( hRing, rect.minx, rect.maxy); + OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny); + OGR_G_AddGeometryDirectly( hSpatialFilterPolygon, hRing ); + OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterPolygon ); + OGR_G_DestroyGeometry( hSpatialFilterPolygon ); + } + + if (layer->debug >= MS_DEBUGLEVEL_VVV) + { + msDebug("msOGRFileWhichShapes: Setting spatial filter to %.15g %.15g %.15g %.15g\n", rect.minx, rect.miny, rect.maxx, rect.maxy ); + } + } + + psInfo->rect = rect; + + /* ------------------------------------------------------------------ + * Apply an attribute filter if we have one prefixed with a WHERE + * keyword in the filter string. Otherwise, ensure the attribute + * filter is clear. + * ------------------------------------------------------------------ */ + if( pszOGRFilter != NULL ) { + + if (layer->debug >= MS_DEBUGLEVEL_VVV) + msDebug("msOGRFileWhichShapes: Setting attribute filter to %s\n", pszOGRFilter ); + + CPLErrorReset(); + if( OGR_L_SetAttributeFilter( psInfo->hLayer, pszOGRFilter ) != OGRERR_NONE ) { + msSetError(MS_OGRERR, "SetAttributeFilter() failed on layer %s. Check logs.", "msOGRFileWhichShapes()", layer->name?layer->name:"(null)"); + msDebug("SetAttributeFilter(%s) failed on layer %s.\n%s\n", pszOGRFilter, layer->name?layer->name:"(null)", CPLGetLastErrorMsg() ); + RELEASE_OGR_LOCK; + msFree(pszOGRFilter); + msFree(select); + return MS_FAILURE; + } + msFree(pszOGRFilter); + } else + OGR_L_SetAttributeFilter( psInfo->hLayer, NULL ); + + } + + msFree(select); + + /* ------------------------------------------------------------------ + * Reset current feature pointer + * ------------------------------------------------------------------ */ + OGR_L_ResetReading( psInfo->hLayer ); + psInfo->last_record_index_read = -1; + + RELEASE_OGR_LOCK; + + return MS_SUCCESS; } /********************************************************************** @@ -1875,8 +2806,10 @@ msOGRFileNextShape(layerObj *layer, shapeObj *shape, if( (hFeature = OGR_L_GetNextFeature( psInfo->hLayer )) == NULL ) { psInfo->last_record_index_read = -1; if( CPLGetLastErrorType() == CE_Failure ) { - msSetError(MS_OGRERR, "%s", "msOGRFileNextShape()", - CPLGetLastErrorMsg() ); + msSetError(MS_OGRERR, "OGR GetNextFeature() error'd. Check logs.", + "msOGRFileNextShape()"); + msDebug("msOGRFileNextShape(): %s\n", + CPLGetLastErrorMsg() ); RELEASE_OGR_LOCK; return MS_FAILURE; } else { @@ -2081,87 +3014,706 @@ int msOGRFileReadTile( layerObj *layer, msOGRFileInfo *psInfo, psInfo->poCurTile = NULL; } - /* -------------------------------------------------------------------- */ - /* If -2 is passed, then seek reset reading of the tileindex. */ - /* We want to start from the beginning even if this file is */ - /* shared between layers or renders. */ - /* -------------------------------------------------------------------- */ - ACQUIRE_OGR_LOCK; - if( targetTile == -2 ) { - OGR_L_ResetReading( psInfo->hLayer ); + /* -------------------------------------------------------------------- */ + /* If -2 is passed, then seek reset reading of the tileindex. */ + /* We want to start from the beginning even if this file is */ + /* shared between layers or renders. */ + /* -------------------------------------------------------------------- */ + ACQUIRE_OGR_LOCK; + if( targetTile == -2 ) { + OGR_L_ResetReading( psInfo->hLayer ); + } + + /* -------------------------------------------------------------------- */ + /* Get the name (connection string really) of the next tile. */ + /* -------------------------------------------------------------------- */ + OGRFeatureH hFeature; + char *connection = NULL; + msOGRFileInfo *psTileInfo = NULL; + int status; + +#ifndef IGNORE_MISSING_DATA +NextFile: +#endif + + if( targetTile < 0 ) + hFeature = OGR_L_GetNextFeature( psInfo->hLayer ); + + else + hFeature = OGR_L_GetFeature( psInfo->hLayer, targetTile ); + + if( hFeature == NULL ) { + RELEASE_OGR_LOCK; + if( targetTile == -1 ) + return MS_DONE; + else + return MS_FAILURE; + + } + + connection = msStrdup( OGR_F_GetFieldAsString( hFeature, + layer->tileitemindex )); + + nFeatureId = (int)OGR_F_GetFID( hFeature ); // FIXME? GetFID() is a 64bit integer in GDAL 2.0 + + OGR_F_Destroy( hFeature ); + + RELEASE_OGR_LOCK; + + /* -------------------------------------------------------------------- */ + /* Open the new tile file. */ + /* -------------------------------------------------------------------- */ + psTileInfo = msOGRFileOpen( layer, connection ); + + free( connection ); + +#ifndef IGNORE_MISSING_DATA + if( psTileInfo == NULL && targetTile == -1 ) + goto NextFile; +#endif + + if( psTileInfo == NULL ) + return MS_FAILURE; + + psTileInfo->nTileId = nFeatureId; + + /* -------------------------------------------------------------------- */ + /* Initialize the spatial query on this file. */ + /* -------------------------------------------------------------------- */ + if( psInfo->rect.minx != 0 || psInfo->rect.maxx != 0 ) { + status = msOGRFileWhichShapes( layer, psInfo->rect, psTileInfo ); + if( status != MS_SUCCESS ) + return status; + } + + psInfo->poCurTile = psTileInfo; + + /* -------------------------------------------------------------------- */ + /* Update the iteminfo in case this layer has a different field */ + /* list. */ + /* -------------------------------------------------------------------- */ + msOGRLayerInitItemInfo( layer ); + + return MS_SUCCESS; +} + +/************************************************************************/ +/* msExprNode */ +/************************************************************************/ + +class msExprNode +{ + public: + std::vector m_aoChildren; + int m_nToken; + std::string m_osVal; + double m_dfVal; + struct tm m_tmVal; + + msExprNode() : m_nToken(0), m_dfVal(0.0) {} + ~msExprNode(); +}; + +msExprNode::~msExprNode() +{ + for(size_t i=0;i aoStackOp, aoStackVal; + while( node != NULL ) + { + if( node->token == '(' ) + { + msExprNode* subExpr = BuildExprTree(node->next, &node, + nParenthesisLevel + 1); + if( subExpr == NULL ) + { + goto fail; + } + aoStackVal.push_back(subExpr); + continue; + } + else if( node->token == ')' ) + { + if( nParenthesisLevel > 0 ) + { + break; + } + goto fail; + } + else if( node->token == '+' || + node->token == '-' || + node->token == '*' || + node->token == '/' || + node->token == '%' || + node->token == MS_TOKEN_LOGICAL_NOT || + node->token == MS_TOKEN_LOGICAL_AND || + node->token == MS_TOKEN_LOGICAL_OR || + node->token == MS_TOKEN_COMPARISON_GE || + node->token == MS_TOKEN_COMPARISON_GT || + node->token == MS_TOKEN_COMPARISON_LE || + node->token == MS_TOKEN_COMPARISON_LT || + node->token == MS_TOKEN_COMPARISON_EQ || + node->token == MS_TOKEN_COMPARISON_IEQ || + node->token == MS_TOKEN_COMPARISON_LIKE || + node->token == MS_TOKEN_COMPARISON_NE || + node->token == MS_TOKEN_COMPARISON_RE || + node->token == MS_TOKEN_COMPARISON_IRE || + node->token == MS_TOKEN_COMPARISON_IN ) + { + while( !aoStackOp.empty() && + exprGetPriority(node->token) <= + exprGetPriority(aoStackOp.back()->m_nToken)) + { + msExprNode* val1 = NULL; + msExprNode* val2 = NULL; + msExprNode* newNode = NULL; + if (aoStackOp.back()->m_nToken != MS_TOKEN_LOGICAL_NOT) + { + if( aoStackVal.empty() ) + goto fail; + val2 = aoStackVal.back(); + aoStackVal.pop_back(); + } + if( aoStackVal.empty() ) + goto fail; + val1 = aoStackVal.back(); + aoStackVal.pop_back(); + + newNode = new msExprNode; + newNode->m_nToken = aoStackOp.back()->m_nToken; + newNode->m_aoChildren.push_back(val1); + if( val2 ) + newNode->m_aoChildren.push_back(val2); + aoStackVal.push_back(newNode); + delete aoStackOp.back(); + aoStackOp.pop_back(); + } + + msExprNode* newNode = new msExprNode; + newNode->m_nToken = node->token; + aoStackOp.push_back(newNode); + } + else if( node->token == ',' ) + { + } + else if( node->token == MS_TOKEN_COMPARISON_INTERSECTS || + node->token == MS_TOKEN_COMPARISON_DISJOINT || + node->token == MS_TOKEN_COMPARISON_TOUCHES || + node->token == MS_TOKEN_COMPARISON_OVERLAPS || + node->token == MS_TOKEN_COMPARISON_CROSSES || + node->token == MS_TOKEN_COMPARISON_DWITHIN || + node->token == MS_TOKEN_COMPARISON_BEYOND || + node->token == MS_TOKEN_COMPARISON_WITHIN || + node->token == MS_TOKEN_COMPARISON_CONTAINS || + node->token == MS_TOKEN_COMPARISON_EQUALS || + node->token == MS_TOKEN_FUNCTION_LENGTH || + node->token == MS_TOKEN_FUNCTION_TOSTRING || + node->token == MS_TOKEN_FUNCTION_COMMIFY || + node->token == MS_TOKEN_FUNCTION_AREA || + node->token == MS_TOKEN_FUNCTION_ROUND || + node->token == MS_TOKEN_FUNCTION_FROMTEXT || + node->token == MS_TOKEN_FUNCTION_BUFFER || + node->token == MS_TOKEN_FUNCTION_DIFFERENCE || + node->token == MS_TOKEN_FUNCTION_SIMPLIFY || + node->token == MS_TOKEN_FUNCTION_SIMPLIFYPT || + node->token == MS_TOKEN_FUNCTION_GENERALIZE || + node->token == MS_TOKEN_FUNCTION_SMOOTHSIA || + node->token == MS_TOKEN_FUNCTION_JAVASCRIPT || + node->token == MS_TOKEN_FUNCTION_UPPER || + node->token == MS_TOKEN_FUNCTION_LOWER || + node->token == MS_TOKEN_FUNCTION_INITCAP || + node->token == MS_TOKEN_FUNCTION_FIRSTCAP ) + { + if( node->next && node->next->token == '(' ) + { + int node_token = node->token; + msExprNode* subExpr = BuildExprTree(node->next->next, &node, + nParenthesisLevel + 1); + if( subExpr == NULL ) + { + goto fail; + } + msExprNode* newNode = new msExprNode; + newNode->m_nToken = node_token; + if( subExpr->m_nToken == 0 ) + { + newNode->m_aoChildren = subExpr->m_aoChildren; + subExpr->m_aoChildren.clear(); + delete subExpr; + } + else + { + newNode->m_aoChildren.push_back(subExpr); + } + aoStackVal.push_back(newNode); + continue; + } + else + goto fail; + } + else if( node->token == MS_TOKEN_LITERAL_NUMBER || + node->token == MS_TOKEN_LITERAL_BOOLEAN ) + { + msExprNode* newNode = new msExprNode; + newNode->m_nToken = node->token; + newNode->m_dfVal = node->tokenval.dblval; + aoStackVal.push_back(newNode); + } + else if( node->token == MS_TOKEN_LITERAL_STRING ) + { + msExprNode* newNode = new msExprNode; + newNode->m_nToken = node->token; + newNode->m_osVal = node->tokenval.strval; + aoStackVal.push_back(newNode); + } + else if( node->token == MS_TOKEN_LITERAL_TIME ) + { + msExprNode* newNode = new msExprNode; + newNode->m_nToken = node->token; + newNode->m_tmVal = node->tokenval.tmval; + aoStackVal.push_back(newNode); + } + else if( node->token == MS_TOKEN_LITERAL_SHAPE ) + { + msExprNode* newNode = new msExprNode; + newNode->m_nToken = node->token; + char *wkt = msShapeToWKT(node->tokenval.shpval); + newNode->m_osVal = wkt; + msFree(wkt); + aoStackVal.push_back(newNode); + } + else if( node->token == MS_TOKEN_BINDING_DOUBLE || + node->token == MS_TOKEN_BINDING_INTEGER || + node->token == MS_TOKEN_BINDING_STRING || + node->token == MS_TOKEN_BINDING_TIME ) + { + msExprNode* newNode = new msExprNode; + newNode->m_nToken = node->token; + newNode->m_osVal = node->tokenval.bindval.item; + aoStackVal.push_back(newNode); + } + else + { + msExprNode* newNode = new msExprNode; + newNode->m_nToken = node->token; + aoStackVal.push_back(newNode); + } + + node = node->next; + } + + while( !aoStackOp.empty() ) + { + msExprNode* val1 = NULL; + msExprNode* val2 = NULL; + msExprNode* newNode = NULL; + if (aoStackOp.back()->m_nToken != MS_TOKEN_LOGICAL_NOT) + { + if( aoStackVal.empty() ) + goto fail; + val2 = aoStackVal.back(); + aoStackVal.pop_back(); + } + if( aoStackVal.empty() ) + goto fail; + val1 = aoStackVal.back(); + aoStackVal.pop_back(); + + newNode = new msExprNode; + newNode->m_nToken = aoStackOp.back()->m_nToken; + newNode->m_aoChildren.push_back(val1); + if( val2 ) + newNode->m_aoChildren.push_back(val2); + aoStackVal.push_back(newNode); + delete aoStackOp.back(); + aoStackOp.pop_back(); + } + + if( aoStackVal.size() == 1 ) + poRet = aoStackVal.back(); + else if( aoStackVal.size() > 1 ) + { + poRet = new msExprNode; + poRet->m_aoChildren = aoStackVal; + } + + if( pNodeNext ) + *pNodeNext = node ? node->next : NULL; + + return poRet; + +fail: + for( size_t i=0; im_nToken == MS_TOKEN_COMPARISON_EQ && + expr->m_aoChildren.size() == 2 && + expr->m_aoChildren[1]->m_nToken == MS_TOKEN_LITERAL_BOOLEAN && + expr->m_aoChildren[1]->m_dfVal == 1.0 ) + { + return msOGRExtractTopSpatialFilter(info, expr->m_aoChildren[0], + pSpatialFilterNode); + } + + if( expr->m_nToken == MS_TOKEN_COMPARISON_INTERSECTS && + expr->m_aoChildren.size() == 2 && + expr->m_aoChildren[1]->m_nToken == MS_TOKEN_LITERAL_SHAPE ) + { + if( info->rect_is_defined ) + { + // Several intersects... + *pSpatialFilterNode = NULL; + info->rect_is_defined = MS_FALSE; + return MS_FALSE; + } + OGRGeometryH hSpatialFilter = NULL; + char* wkt = const_cast(expr->m_aoChildren[1]->m_osVal.c_str()); + OGRErr e = OGR_G_CreateFromWkt(&wkt, NULL, &hSpatialFilter); + if (e == OGRERR_NONE) { + OGREnvelope env; + OGR_G_GetEnvelope(hSpatialFilter, &env); + info->rect.minx = env.MinX; + info->rect.miny = env.MinY; + info->rect.maxx = env.MaxX; + info->rect.maxy = env.MaxY; + info->rect_is_defined = true; + *pSpatialFilterNode = expr; + OGR_G_DestroyGeometry(hSpatialFilter); + return MS_TRUE; + } + return MS_FALSE; + } + + if( expr->m_nToken == MS_TOKEN_LOGICAL_AND && + expr->m_aoChildren.size() == 2 ) + { + return msOGRExtractTopSpatialFilter(info, expr->m_aoChildren[0], + pSpatialFilterNode) && + msOGRExtractTopSpatialFilter(info, expr->m_aoChildren[1], + pSpatialFilterNode); } - /* -------------------------------------------------------------------- */ - /* Get the name (connection string really) of the next tile. */ - /* -------------------------------------------------------------------- */ - OGRFeatureH hFeature; - char *connection = NULL; - msOGRFileInfo *psTileInfo = NULL; - int status; + return MS_TRUE; +} -#ifndef IGNORE_MISSING_DATA -NextFile: -#endif +/********************************************************************** + * msOGRTranslatePartialMSExpressionToOGRSQL() + * + * Tries to partially translate a mapserver expression to SQL + **********************************************************************/ - if( targetTile < 0 ) - hFeature = OGR_L_GetNextFeature( psInfo->hLayer ); +static std::string msOGRGetTokenText(int nToken) +{ + switch( nToken ) + { + case '*': + case '+': + case '-': + case '/': + case '%': + return std::string(1, static_cast(nToken)); + + case MS_TOKEN_COMPARISON_GE: return ">="; + case MS_TOKEN_COMPARISON_GT: return ">"; + case MS_TOKEN_COMPARISON_LE: return "<="; + case MS_TOKEN_COMPARISON_LT: return "<"; + case MS_TOKEN_COMPARISON_EQ: return "="; + case MS_TOKEN_COMPARISON_NE: return "!="; + case MS_TOKEN_COMPARISON_LIKE: return "LIKE"; - else - hFeature = OGR_L_GetFeature( psInfo->hLayer, targetTile ); + default: + return std::string(); + } +} - if( hFeature == NULL ) { - RELEASE_OGR_LOCK; - if( targetTile == -1 ) - return MS_DONE; - else - return MS_FAILURE; +static std::string msOGRTranslatePartialInternal(layerObj* layer, + const msExprNode* expr, + const msExprNode* spatialFilterNode, + bool& bPartialFilter) +{ + switch( expr->m_nToken ) + { + case MS_TOKEN_LOGICAL_NOT: + { + std::string osTmp(msOGRTranslatePartialInternal( + layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter )); + if( osTmp.empty() ) + return std::string(); + return "(NOT " + osTmp + ")"; + } - } + case MS_TOKEN_LOGICAL_AND: + { + // We can deal with partially translated children + std::string osTmp1(msOGRTranslatePartialInternal( + layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter )); + std::string osTmp2(msOGRTranslatePartialInternal( + layer, expr->m_aoChildren[1], spatialFilterNode, bPartialFilter )); + if( !osTmp1.empty() && !osTmp2.empty() ) + { + return "(" + osTmp1 + " AND " + osTmp2 + ")"; + } + else if( !osTmp1.empty() ) + return osTmp1; + else + return osTmp2; + } - connection = msStrdup( OGR_F_GetFieldAsString( hFeature, - layer->tileitemindex )); + case MS_TOKEN_LOGICAL_OR: + { + // We can NOT deal with partially translated children + std::string osTmp1(msOGRTranslatePartialInternal( + layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter )); + std::string osTmp2(msOGRTranslatePartialInternal( + layer, expr->m_aoChildren[1], spatialFilterNode, bPartialFilter )); + if( !osTmp1.empty() && !osTmp2.empty() ) + { + return "(" + osTmp1 + " OR " + osTmp2 + ")"; + } + else + return std::string(); + } - nFeatureId = (int)OGR_F_GetFID( hFeature ); // FIXME? GetFID() is a 64bit integer in GDAL 2.0 + case '*': + case '+': + case '-': + case '/': + case '%': + case MS_TOKEN_COMPARISON_GE: + case MS_TOKEN_COMPARISON_GT: + case MS_TOKEN_COMPARISON_LE: + case MS_TOKEN_COMPARISON_LT: + case MS_TOKEN_COMPARISON_EQ: + case MS_TOKEN_COMPARISON_NE: + { + std::string osTmp1(msOGRTranslatePartialInternal( + layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter )); + std::string osTmp2(msOGRTranslatePartialInternal( + layer, expr->m_aoChildren[1], spatialFilterNode, bPartialFilter )); + if( !osTmp1.empty() && !osTmp2.empty() ) + { + if( expr->m_nToken == MS_TOKEN_COMPARISON_EQ && + osTmp2 == "'_MAPSERVER_NULL_'" ) + { + return "(" + osTmp1 + " IS NULL )"; + } + if( expr->m_aoChildren[1]->m_nToken == MS_TOKEN_LITERAL_STRING ) + { + char md_item_name[256]; + snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", + expr->m_aoChildren[0]->m_osVal.c_str() ); + const char* type = + msLookupHashTable(&(layer->metadata), md_item_name); + // Cast if needed (or unsure) + if( type == NULL || !EQUAL(type, "Character") ) + { + osTmp1 = "CAST(" + osTmp1 + " AS CHARACTER(4096))"; + } + } + return "(" + osTmp1 + " " + msOGRGetTokenText(expr->m_nToken) + + " " + osTmp2 + ")"; + } + else + return std::string(); + } - OGR_F_Destroy( hFeature ); + case MS_TOKEN_COMPARISON_RE: + { + std::string osTmp1(msOGRTranslatePartialInternal( + layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter )); + if( expr->m_aoChildren[1]->m_nToken != MS_TOKEN_LITERAL_STRING ) + { + return std::string(); + } + std::string osRE("'"); + const size_t nSize = expr->m_aoChildren[1]->m_osVal.size(); + bool bHasUsedEscape = false; + for( size_t i=0; im_aoChildren[1]->m_osVal[i] == '^' ) + continue; + if( expr->m_aoChildren[1]->m_osVal[i] == '.' ) + { + if( i+1m_aoChildren[1]->m_osVal[i+1] == '*' ) + { + osRE += "%"; + i++; + } + else + { + osRE += "_"; + } + } + else if( expr->m_aoChildren[1]->m_osVal[i] == '\\' && + i+1m_aoChildren[1]->m_osVal[i+1]; + i++; + } + else if( expr->m_aoChildren[1]->m_osVal[i] == 'X' || + expr->m_aoChildren[1]->m_osVal[i] == '%' || + expr->m_aoChildren[1]->m_osVal[i] == '_' ) + { + bHasUsedEscape = true; + osRE += 'X'; + osRE += expr->m_aoChildren[1]->m_osVal[i]; + } + else + { + osRE += expr->m_aoChildren[1]->m_osVal[i]; + } + } + osRE += "'"; + char md_item_name[256]; + snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", + expr->m_aoChildren[0]->m_osVal.c_str() ); + const char* type = + msLookupHashTable(&(layer->metadata), md_item_name); + // Cast if needed (or unsure) + if( type == NULL || !EQUAL(type, "Character") ) + { + osTmp1 = "CAST(" + osTmp1 + " AS CHARACTER(4096))"; + } + std::string osRet( "(" + osTmp1 + " LIKE " + osRE ); + if( bHasUsedEscape ) + osRet += " ESCAPE 'X'"; + osRet += ")"; + return osRet; + } - RELEASE_OGR_LOCK; + case MS_TOKEN_COMPARISON_IN: + { + std::string osTmp1(msOGRTranslatePartialInternal( + layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter )); + std::string osRet = "(" + osTmp1 + " IN ("; + for( size_t i=0; i< expr->m_aoChildren[1]->m_aoChildren.size(); ++i ) + { + if( i > 0 ) + osRet += ", "; + osRet += msOGRTranslatePartialInternal( + layer, expr->m_aoChildren[1]->m_aoChildren[i], + spatialFilterNode, bPartialFilter ); + } + osRet += ")"; + return osRet; + } - /* -------------------------------------------------------------------- */ - /* Open the new tile file. */ - /* -------------------------------------------------------------------- */ - psTileInfo = msOGRFileOpen( layer, connection ); + case MS_TOKEN_LITERAL_NUMBER: + case MS_TOKEN_LITERAL_BOOLEAN: + { + return std::string(CPLSPrintf("%.18g", expr->m_dfVal)); + } - free( connection ); + case MS_TOKEN_LITERAL_STRING: + { + char *stresc = msOGREscapeSQLParam(layer, expr->m_osVal.c_str()); + std::string osRet("'" + std::string(stresc) + "'"); + msFree(stresc); + return osRet; + } -#ifndef IGNORE_MISSING_DATA - if( psTileInfo == NULL && targetTile == -1 ) - goto NextFile; + case MS_TOKEN_LITERAL_TIME: + { +#ifdef notdef + // Breaks tests in msautotest/wxs/wfs_time_ogr.map + return std::string(CPLSPrintf("'%04d/%02d/%02d %02d:%02d:%02d'", + expr->m_tmVal.tm_year+1900, + expr->m_tmVal.tm_mon+1, + expr->m_tmVal.tm_mday, + expr->m_tmVal.tm_hour, + expr->m_tmVal.tm_min, + expr->m_tmVal.tm_sec)); #endif + return std::string(); + } - if( psTileInfo == NULL ) - return MS_FAILURE; - - psTileInfo->nTileId = nFeatureId; - - /* -------------------------------------------------------------------- */ - /* Initialize the spatial query on this file. */ - /* -------------------------------------------------------------------- */ - if( psInfo->rect.minx != 0 || psInfo->rect.maxx != 0 ) { - status = msOGRFileWhichShapes( layer, psInfo->rect, psTileInfo ); - if( status != MS_SUCCESS ) - return status; - } - - psInfo->poCurTile = psTileInfo; + case MS_TOKEN_BINDING_DOUBLE: + case MS_TOKEN_BINDING_INTEGER: + case MS_TOKEN_BINDING_STRING: + case MS_TOKEN_BINDING_TIME: + { + char* pszTmp = msOGRGetQuotedItem(layer, expr->m_osVal.c_str()); + std::string osRet(pszTmp); + msFree(pszTmp); + return osRet; + } - /* -------------------------------------------------------------------- */ - /* Update the iteminfo in case this layer has a different field */ - /* list. */ - /* -------------------------------------------------------------------- */ - msOGRLayerInitItemInfo( layer ); + case MS_TOKEN_COMPARISON_INTERSECTS: + { + if( expr != spatialFilterNode ) + bPartialFilter = true; + return std::string(); + } - return MS_SUCCESS; + default: + { + bPartialFilter = true; + return std::string(); + } + } } #endif /* def USE_OGR */ @@ -2170,6 +3722,221 @@ int msOGRFileReadTile( layerObj *layer, msOGRFileInfo *psInfo, * Here comes the REAL stuff... the functions below are called by maplayer.c * ================================================================== */ +/********************************************************************** + * msOGRTranslateMsExpressionToOGRSQL() + * + * Tries to translate a mapserver expression to OGR or driver native SQL + **********************************************************************/ +static int msOGRTranslateMsExpressionToOGRSQL(layerObj* layer, + expressionObj* psFilter, + char *filteritem) +{ +#ifdef USE_OGR + msOGRFileInfo *info = (msOGRFileInfo *)layer->layerinfo; + + msFree(layer->filter.native_string); + layer->filter.native_string = NULL; + + msFree(info->pszWHERE); + info->pszWHERE = NULL; + + // reasons to not produce native string: not simple layer, or an explicit deny + char *do_this = msLayerGetProcessingKey(layer, "NATIVE_SQL"); // default is YES + if (do_this && strcmp(do_this, "NO") == 0) { + return MS_SUCCESS; + } + + tokenListNodeObjPtr node = psFilter->tokens; + msExprNode* expr = BuildExprTree(node, NULL, 0); + info->rect_is_defined = MS_FALSE; + const msExprNode* spatialFilterNode = NULL; + if( expr ) + msOGRExtractTopSpatialFilter( info, expr, &spatialFilterNode ); + + // more reasons to not produce native string: not a recognized driver + if (!info->dialect) + { + // in which case we might still want to try to get a partial WHERE clause + if( filteritem == NULL && expr ) + { + bool bPartialFilter = false; + std::string osSQL( msOGRTranslatePartialInternal(layer, expr, + spatialFilterNode, + bPartialFilter) ); + if( !osSQL.empty() ) + { + info->pszWHERE = msStrdup(osSQL.c_str()); + if( bPartialFilter ) + { + msDebug("Full filter has only been partially " + "translated to OGR filter %s\n", + info->pszWHERE); + } + } + else if( bPartialFilter ) + { + msDebug("Filter could not be translated to OGR filter\n"); + } + } + delete expr; + return MS_SUCCESS; + } + + char *sql = NULL; + + // node may be NULL if layer->filter.string != NULL and filteritem != NULL + // this is simple filter but string is regex + if (node == NULL && filteritem != NULL && layer->filter.string != NULL) { + sql = msStringConcatenate(sql, "\""); + sql = msStringConcatenate(sql, filteritem); + sql = msStringConcatenate(sql, "\""); + if (EQUAL(info->dialect, "PostgreSQL") ) { + sql = msStringConcatenate(sql, " ~ "); + } else { + sql = msStringConcatenate(sql, " LIKE "); + } + sql = msStringConcatenate(sql, "'"); + sql = msStringConcatenate(sql, layer->filter.string); + sql = msStringConcatenate(sql, "'"); + } + + while (node != NULL) { + + if (node->next && node->next->token == MS_TOKEN_COMPARISON_IEQ) { + char *left = msOGRGetToken(layer, &node); + node = node->next; // skip = + char *right = msOGRGetToken(layer, &node); + sql = msStringConcatenate(sql, "upper("); + sql = msStringConcatenate(sql, left); + sql = msStringConcatenate(sql, ")"); + sql = msStringConcatenate(sql, "="); + sql = msStringConcatenate(sql, "upper("); + sql = msStringConcatenate(sql, right); + sql = msStringConcatenate(sql, ")"); + int ok = left && right; + msFree(left); + msFree(right); + if (!ok) { + goto fail; + } + continue; + } + + switch(node->token) { + case MS_TOKEN_COMPARISON_INTERSECTS: + case MS_TOKEN_COMPARISON_DISJOINT: + case MS_TOKEN_COMPARISON_TOUCHES: + case MS_TOKEN_COMPARISON_OVERLAPS: + case MS_TOKEN_COMPARISON_CROSSES: + case MS_TOKEN_COMPARISON_DWITHIN: + case MS_TOKEN_COMPARISON_BEYOND: + case MS_TOKEN_COMPARISON_WITHIN: + case MS_TOKEN_COMPARISON_CONTAINS: + case MS_TOKEN_COMPARISON_EQUALS:{ + int token = node->token; + char *fct = msOGRGetToken(layer, &node); + node = node->next; // skip ( + char *a1 = msOGRGetToken(layer, &node); + node = node->next; // skip , + char *a2 = msOGRGetToken(layer, &node); + char *a3 = NULL; + if (token == MS_TOKEN_COMPARISON_DWITHIN || token == MS_TOKEN_COMPARISON_BEYOND) { + node = node->next; // skip , + a3 = msOGRGetToken(layer, &node); + } + node = node->next; // skip ) + char *eq = msOGRGetToken(layer, &node); + char *rval = msOGRGetToken(layer, &node); + if (strcmp(eq, " != ") == 0 || strcmp(rval, "FALSE") == 0) { + sql = msStringConcatenate(sql, "NOT "); + } + // FIXME: case rval is more complex + sql = msStringConcatenate(sql, fct); + sql = msStringConcatenate(sql, "("); + sql = msStringConcatenate(sql, a1); + sql = msStringConcatenate(sql, ","); + sql = msStringConcatenate(sql, a2); + if (token == MS_TOKEN_COMPARISON_DWITHIN || token == MS_TOKEN_COMPARISON_BEYOND) { + sql = msStringConcatenate(sql, ")"); + if (token == MS_TOKEN_COMPARISON_DWITHIN) + sql = msStringConcatenate(sql, "<="); + else + sql = msStringConcatenate(sql, ">"); + sql = msStringConcatenate(sql, a3); + } else { + sql = msStringConcatenate(sql, ")"); + } + int ok = fct && a1 && a2 && eq && rval; + if (token == MS_TOKEN_COMPARISON_DWITHIN) { + ok = ok && a3; + } + msFree(fct); + msFree(a1); + msFree(a2); + msFree(a3); + msFree(eq); + msFree(rval); + if (!ok) { + goto fail; + } + break; + } + default: { + char *token = msOGRGetToken(layer, &node); + if (!token) { + goto fail; + } + sql = msStringConcatenate(sql, token); + msFree(token); + } + } + } + + layer->filter.native_string = sql; + delete expr; + return MS_SUCCESS; +fail: + // error producing native string + msDebug("Note: Error parsing token list, could produce only: %s. Trying in partial mode\n", sql); + msFree(sql); + + // in which case we might still want to try to get a partial WHERE clause + if( expr ) + { + bool bPartialFilter = false; + std::string osSQL( msOGRTranslatePartialInternal(layer, expr, + spatialFilterNode, + bPartialFilter) ); + if( !osSQL.empty() ) + { + info->pszWHERE = msStrdup(osSQL.c_str()); + if( bPartialFilter ) + { + msDebug("Full filter has only been partially " + "translated to OGR filter %s\n", + info->pszWHERE); + } + } + else if( bPartialFilter ) + { + msDebug("Filter could not be translated to OGR filter\n"); + } + } + delete expr; + + return MS_SUCCESS; +#else + /* ------------------------------------------------------------------ + * OGR Support not included... + * ------------------------------------------------------------------ */ + + msSetError(MS_MISCERR, "OGR support is not available.", + "msOGRTranslateMsExpressionToOGRSQL()"); + return(MS_FAILURE); + +#endif /* USE_OGR */ +} + /********************************************************************** * msOGRLayerOpen() * @@ -2359,6 +4126,35 @@ static int msOGRLayerIsOpen(layerObj *layer) #endif /* USE_OGR */ } +int msOGRIsSpatialite(layerObj* layer) +{ +#ifdef USE_OGR + msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; + if (psInfo && psInfo->dialect && + EQUAL(psInfo->dialect, "Spatialite") ) + { + // reasons to not produce native string: not simple layer, or an explicit deny + char *do_this = msLayerGetProcessingKey(layer, "NATIVE_SQL"); // default is YES + if (do_this && strcmp(do_this, "NO") == 0) { + return MS_FALSE; + } + return MS_TRUE; + } + + return MS_FALSE; + +#else + /* ------------------------------------------------------------------ + * OGR Support not included... + * ------------------------------------------------------------------ */ + + msSetError(MS_MISCERR, "OGR support is not available.", "msOGRIsSpatialite()"); + return(MS_FALSE); + +#endif /* USE_OGR */ +} + + /********************************************************************** * msOGRLayerWhichShapes() * @@ -2552,7 +4348,16 @@ static int msOGRLayerInitItemInfo(layerObj *layer) itemindexes[i] = MSOGR_SYMBOLPARAMINDEX + atoi(layer->items[i] + MSOGR_SYMBOLPARAMNAMELEN); else + { itemindexes[i] = OGR_FD_GetFieldIndex( hDefn, layer->items[i] ); + if( itemindexes[i] == -1 ) + { + if( EQUAL( layer->items[i], OGR_L_GetFIDColumn( psInfo->hLayer ) ) ) + { + itemindexes[i] = MSOGR_FID_INDEX; + } + } + } if(itemindexes[i] == -1) { msSetError(MS_OGRERR, "Invalid Field name: %s", @@ -3611,15 +5416,20 @@ char *msOGREscapePropertyName(layerObj *layer, const char *pszString) { #ifdef USE_OGR char* pszEscapedStr =NULL; - int i =0; if(layer && pszString && strlen(pszString) > 0) { - unsigned char ch; - for(i=0; (ch = ((unsigned char*)pszString)[i]) != '\0'; i++) { - if ( !(isalnum(ch) || ch == '_' || ch > 127) ) { - return msStrdup("invalid_property_name"); - } + pszEscapedStr = (char*) msSmallMalloc( strlen(pszString) * 2 + 1 ); + int j = 0; + for( int i = 0; pszString[i] != '\0'; ++i ) + { + if( pszString[i] == '"' ) + { + pszEscapedStr[j++] = '"'; + pszEscapedStr[j++] = '"'; + } + else + pszEscapedStr[j++] = pszString[i]; } - pszEscapedStr = msStrdup(pszString); + pszEscapedStr[j] = 0; } return pszEscapedStr; #else @@ -3639,6 +5449,55 @@ static int msOGRLayerSupportsCommonFilters(layerObj *layer) return MS_FALSE; } +static void msOGREnablePaging(layerObj *layer, int value) +{ +#ifdef USE_OGR + msOGRFileInfo *layerinfo = NULL; + + if (layer->debug) { + msDebug("msOGREnablePaging(%d) called.\n", value); + } + + if(!msOGRLayerIsOpen(layer)) + msOGRLayerOpenVT(layer); + + assert( layer->layerinfo != NULL); + + layerinfo = (msOGRFileInfo *)layer->layerinfo; + layerinfo->bPaging = value; + +#else + msSetError( MS_MISCERR, + "OGR support is not available.", + "msOGREnablePaging()"); +#endif + return; +} + +static int msOGRGetPaging(layerObj *layer) +{ +#ifdef USE_OGR + msOGRFileInfo *layerinfo = NULL; + + if (layer->debug) { + msDebug("msOGRGetPaging called.\n"); + } + + if(!msOGRLayerIsOpen(layer)) + msOGRLayerOpenVT(layer); + + assert( layer->layerinfo != NULL); + + layerinfo = (msOGRFileInfo *)layer->layerinfo; + return layerinfo->bPaging; +#else + msSetError( MS_MISCERR, + "OGR support is not available.", + "msOGREnablePaging()"); + return MS_FAILURE; +#endif +} + /************************************************************************/ /* msOGRLayerInitializeVirtualTable() */ /************************************************************************/ @@ -3647,7 +5506,7 @@ int msOGRLayerInitializeVirtualTable(layerObj *layer) assert(layer != NULL); assert(layer->vtable != NULL); - /* layer->vtable->LayerTranslateFilter, use default */ + layer->vtable->LayerTranslateFilter = msOGRTranslateMsExpressionToOGRSQL; layer->vtable->LayerSupportsCommonFilters = msOGRLayerSupportsCommonFilters; layer->vtable->LayerInitItemInfo = msOGRLayerInitItemInfo; @@ -3670,7 +5529,8 @@ int msOGRLayerInitializeVirtualTable(layerObj *layer) layer->vtable->LayerEscapeSQLParam = msOGREscapeSQLParam; layer->vtable->LayerEscapePropertyName = msOGREscapePropertyName; - + layer->vtable->LayerEnablePaging = msOGREnablePaging; + layer->vtable->LayerGetPaging = msOGRGetPaging; return MS_SUCCESS; } @@ -3803,4 +5663,3 @@ char *msOGRShapeToWKT(shapeObj *shape) return NULL; #endif } - diff --git a/mapogroutput.c b/mapogroutput.c index c105fdfd09..0c1def249f 100644 --- a/mapogroutput.c +++ b/mapogroutput.c @@ -767,6 +767,7 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders ) /* Create a subdirectory to handle this request. */ /* -------------------------------------------------------------------- */ if( !EQUAL(storage,"stream") ) { + const char* dir_to_create; if (strlen(base_dir) > 0) request_dir = msTmpFile(map, NULL, base_dir, "" ); else @@ -775,11 +776,19 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders ) if( request_dir[strlen(request_dir)-1] == '.' ) request_dir[strlen(request_dir)-1] = '\0'; - if( VSIMkdir( request_dir, 0777 ) != 0 ) { + dir_to_create = request_dir; + /* Workaround issue in GDAL versions released at this time : + * GDAL issue fixed per https://trac.osgeo.org/gdal/ticket/6991 */ + if( EQUAL(storage,"memory") && EQUAL(format->driver+4, "ESRI Shapefile") ) + { + dir_to_create = base_dir; + } + + if( VSIMkdir( dir_to_create, 0777 ) != 0 ) { msSetError( MS_MISCERR, "Attempt to create directory '%s' failed.", "msOGRWriteFromQuery()", - request_dir ); + dir_to_create ); return MS_FAILURE; } } else diff --git a/maporaclespatial.c b/maporaclespatial.c index afc679c516..efbfa1f811 100644 --- a/maporaclespatial.c +++ b/maporaclespatial.c @@ -38,6 +38,7 @@ #include "mapserver.h" #include "maptime.h" +#include "mapows.h" #include @@ -399,8 +400,10 @@ static int msSplitData( char *data, char **geometry_column_name, char **table_na break; /* stop on spaces */ /* double the size of the table_name array if necessary */ if (i == table_name_size) { + size_t tgt_offset = tgt - *table_name; table_name_size *= 2; *table_name = (char *) realloc(*table_name,sizeof(char *) * table_name_size); + tgt = *table_name + tgt_offset; } *tgt = *src; } @@ -1704,7 +1707,7 @@ static int osGetOrdinates(msOracleSpatialDataHandler *dthand, msOracleSpatialHan } /* end of not-null-object if */ if (compound_type){ - if(gtype == 2003) + if (gtype == 2003 || gtype == 2007) shape->type = MS_SHAPE_POLYGON; msFreeShape(&newshape); } @@ -2016,7 +2019,7 @@ int msOracleSpatialLayerWhichShapes( layerObj *layer, rectObj rect, int isQuery) /* define SQL query */ for( i=0; i < layer->numitems; ++i ) { - snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s, ", layer->items[i] ); + snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "\"%s\", ", layer->items[i] ); } /*we add the uniqueid if it was not part of the current item list*/ @@ -3953,7 +3956,7 @@ PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj *layer) assert(layer != NULL); assert(vtable != NULL); - layer->vtable->LayerTranslateFilter = msOracleSpatialLayerTranslateFilter; + vtable->LayerTranslateFilter = msOracleSpatialLayerTranslateFilter; vtable->LayerInitItemInfo = msOracleSpatialLayerInitItemInfo; @@ -3972,7 +3975,7 @@ PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj *layer) vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; //vtable->LayerSetTimeFilter = msOracleSpatialLayerSetTimeFilter; - vtable->LayerEscapePropertyName = msOracleSpatialEscapePropertyName; + //vtable->LayerEscapePropertyName = msOracleSpatialEscapePropertyName; /* layer->vtable->LayerGetNumFeatures, use default */ /* layer->vtable->LayerGetAutoProjection = msOracleSpatialLayerGetAutoProjection; Disabled until tested */ vtable->LayerEnablePaging = msOracleSpatialEnablePaging; @@ -4006,7 +4009,7 @@ int msOracleSpatialLayerInitializeVirtualTable(layerObj *layer) layer->vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; //layer->vtable->LayerSetTimeFilter = msOracleSpatialLayerSetTimeFilter; - layer->vtable->LayerEscapePropertyName = msOracleSpatialEscapePropertyName; + //layer->vtable->LayerEscapePropertyName = msOracleSpatialEscapePropertyName; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ /* layer->vtable->LayerGetAutoProjection = msOracleSpatialLayerGetAutoProjection; Disabled until tested */ diff --git a/mapoutput.c b/mapoutput.c index bc409f9186..a539e40dfe 100644 --- a/mapoutput.c +++ b/mapoutput.c @@ -904,7 +904,8 @@ void msGetOutputFormatMimeListWMS( mapObj *map, char **mime_list, int max_mime ) strcasecmp(map->outputformatlist[i]->driver, "CAIRO/SVG")==0 || strcasecmp(map->outputformatlist[i]->driver, "CAIRO/PDF")==0 || strcasecmp(map->outputformatlist[i]->driver, "kml")==0 || - strcasecmp(map->outputformatlist[i]->driver, "kmz")==0)) + strcasecmp(map->outputformatlist[i]->driver, "kmz")==0 || + strcasecmp(map->outputformatlist[i]->driver, "UTFGRID")==0)) mime_list[mime_count++] = map->outputformatlist[i]->mimetype; } } diff --git a/mapowscommon.c b/mapowscommon.c index 0c86c87025..24609a4a01 100644 --- a/mapowscommon.c +++ b/mapowscommon.c @@ -83,7 +83,7 @@ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "title", validated_language); - psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "Title", BAD_CAST value); + psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Title", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_title\" missing for ows:Title")); @@ -91,7 +91,7 @@ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "abstract", validated_language); - psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "Abstract", BAD_CAST value); + psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Abstract", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_abstract\" was missing for ows:Abstract")); @@ -100,7 +100,7 @@ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "keywordlist", validated_language); if (value) { - psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL); + psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL); msLibXml2GenerateList(psNode, psNsOws, "Keyword", value, ','); } @@ -108,7 +108,7 @@ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map, xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_keywordlist\" was missing for ows:KeywordList")); } - psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "ServiceType", BAD_CAST servicetype); + psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ServiceType", BAD_CAST servicetype); xmlNewProp(psNode, BAD_CAST "codeSpace", BAD_CAST MS_OWSCOMMON_OGC_CODESPACE); @@ -116,7 +116,7 @@ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "fees", validated_language); - psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "Fees", BAD_CAST value); + psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Fees", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_fees\" was missing for ows:Fees")); @@ -124,7 +124,7 @@ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "accessconstraints", validated_language); - psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "AccessConstraints", BAD_CAST value); + psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "AccessConstraints", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_accessconstraints\" was missing for ows:AccessConstraints")); @@ -169,13 +169,13 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactorganization", validated_language); - psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "ProviderName", BAD_CAST value); + psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ProviderName", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Mandatory metadata \"ows_contactorganization\" was missing for ows:ProviderName")); } - psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "ProviderSite", NULL); + psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ProviderSite", NULL); xmlNewNsProp(psNode, psNsXLink, BAD_CAST "type", BAD_CAST "simple"); @@ -187,11 +187,11 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink, xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_service_onlineresource\" was missing for ows:ProviderSite/@xlink:href")); } - psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "ServiceContact", NULL); + psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ServiceContact", NULL); value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactperson", validated_language); - psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "IndividualName", BAD_CAST value); + psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "IndividualName", BAD_CAST value); if (!value) { xmlAddSibling(psSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactperson\" was missing for ows:IndividualName")); @@ -199,19 +199,19 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactposition", validated_language); - psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "PositionName", BAD_CAST value); + psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "PositionName", BAD_CAST value); if (!value) { xmlAddSibling(psSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactposition\" was missing for ows:PositionName")); } - psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "ContactInfo", NULL); + psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "ContactInfo", NULL); - psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "Phone", NULL); + psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "Phone", NULL); value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactvoicetelephone", validated_language); - psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "Voice", BAD_CAST value); + psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "Voice", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactvoicetelephone\" was missing for ows:Voice")); @@ -219,17 +219,17 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactfacsimiletelephone", validated_language); - psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "Facsimile", BAD_CAST value); + psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "Facsimile", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactfacsimiletelephone\" was missing for ows:Facsimile")); } - psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "Address", NULL); + psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "Address", NULL); value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "address", validated_language); - psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "DeliveryPoint", BAD_CAST value); + psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "DeliveryPoint", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_address\" was missing for ows:DeliveryPoint")); @@ -237,7 +237,7 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "city", validated_language); - psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "City", BAD_CAST value); + psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "City", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_city\" was missing for ows:City")); @@ -245,7 +245,7 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "stateorprovince", validated_language); - psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "AdministrativeArea", BAD_CAST value); + psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "AdministrativeArea", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_stateorprovince\" was missing for ows:AdministrativeArea")); @@ -253,7 +253,7 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "postcode", validated_language); - psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "PostalCode", BAD_CAST value); + psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "PostalCode", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_postcode\" was missing for ows:PostalCode")); @@ -261,7 +261,7 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "country", validated_language); - psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "Country", BAD_CAST value); + psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "Country", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_country\" was missing for ows:Country")); @@ -269,13 +269,13 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactelectronicmailaddress", validated_language); - psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "ElectronicMailAddress", BAD_CAST value); + psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "ElectronicMailAddress", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactelectronicmailaddress\" was missing for ows:ElectronicMailAddress")); } - psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "OnlineResource", NULL); + psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "OnlineResource", NULL); xmlNewNsProp(psSubSubNode, psNsXLink, BAD_CAST "type", BAD_CAST "simple"); @@ -289,7 +289,7 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "hoursofservice", validated_language); - psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "HoursOfService", BAD_CAST value); + psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "HoursOfService", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_hoursofservice\" was missing for ows:HoursOfService")); @@ -297,7 +297,7 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactinstructions", validated_language); - psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "ContactInstructions", BAD_CAST value); + psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "ContactInstructions", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactinstructions\" was missing for ows:ContactInstructions")); @@ -305,7 +305,7 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink, value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "role", validated_language); - psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "Role", BAD_CAST value); + psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "Role", BAD_CAST value); if (!value) { xmlAddSibling(psSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_role\" was missing for ows:Role")); @@ -489,9 +489,7 @@ xmlNodePtr msOWSCommonExceptionReport(xmlNsPtr psNsOws, int ows_version, const c } if (ExceptionText != NULL) { - char* errorMessage = msEncodeHTMLEntities(ExceptionText); - xmlNewChild(psMainNode, NULL, BAD_CAST "ExceptionText", BAD_CAST errorMessage); - msFree(errorMessage); + xmlNewTextChild(psMainNode, NULL, BAD_CAST "ExceptionText", BAD_CAST ExceptionText); } free(xsi_schemaLocation); diff --git a/mappostgis.c b/mappostgis.c index 650ade0839..cc4edf8bba 100644 --- a/mappostgis.c +++ b/mappostgis.c @@ -766,57 +766,13 @@ int arcCircleCenter(const pointObj *p1, const pointObj *p2, const pointObj *p3, pointObj *center, double *radius) { pointObj c; - double r; - - /* Components of the matrices. */ - double x1sq = p1->x * p1->x; - double x2sq = p2->x * p2->x; - double x3sq = p3->x * p3->x; - double y1sq = p1->y * p1->y; - double y2sq = p2->y * p2->y; - double y3sq = p3->y * p3->y; - double matrix_num_x[9]; - double matrix_num_y[9]; - double matrix_denom[9]; - - /* Intialize matrix_num_x */ - matrix_num_x[0] = x1sq+y1sq; - matrix_num_x[1] = p1->y; - matrix_num_x[2] = 1.0; - matrix_num_x[3] = x2sq+y2sq; - matrix_num_x[4] = p2->y; - matrix_num_x[5] = 1.0; - matrix_num_x[6] = x3sq+y3sq; - matrix_num_x[7] = p3->y; - matrix_num_x[8] = 1.0; - - /* Intialize matrix_num_y */ - matrix_num_y[0] = p1->x; - matrix_num_y[1] = x1sq+y1sq; - matrix_num_y[2] = 1.0; - matrix_num_y[3] = p2->x; - matrix_num_y[4] = x2sq+y2sq; - matrix_num_y[5] = 1.0; - matrix_num_y[6] = p3->x; - matrix_num_y[7] = x3sq+y3sq; - matrix_num_y[8] = 1.0; - - /* Intialize matrix_denom */ - matrix_denom[0] = p1->x; - matrix_denom[1] = p1->y; - matrix_denom[2] = 1.0; - matrix_denom[3] = p2->x; - matrix_denom[4] = p2->y; - matrix_denom[5] = 1.0; - matrix_denom[6] = p3->x; - matrix_denom[7] = p3->y; - matrix_denom[8] = 1.0; + double dx21, dy21, dx31, dy31, h21, h31, d, r; /* Circle is closed, so p2 must be opposite p1 & p3. */ - if ( FP_EQ(p1->x,p3->x) && FP_EQ(p1->y,p3->y) ) { - c.x = (p1->x + p2->x) / 2.0; - c.y = (p1->y + p2->y) / 2.0; - r = sqrt( (p1->x - p2->x) * (p1->x - p2->x) + (p1->y - p2->y) * (p1->y - p2->y) ) / 2.0; + if ((fabs(p1->x - p3->x) < FP_EPSILON) && (fabs(p1->y-p3->y) < FP_EPSILON)) { + c.x = p1->x + (p2->x - p1->x) / 2.0; + c.y = p1->y + (p2->y - p1->y) / 2.0; + r = sqrt(pow(c.x - p1->x, 2.0) + pow(c.y - p1->y, 2.0)); } /* There is no circle here, the points are actually co-linear */ else if ( arcSegmentSide(p1, p3, p2) == FP_COLINEAR ) { @@ -824,13 +780,22 @@ arcCircleCenter(const pointObj *p1, const pointObj *p2, const pointObj *p3, poin } /* Calculate the center and radius. */ else { - double denom = 2.0 * arcDeterminant3x3(matrix_denom); - /* Center components */ - c.x = arcDeterminant3x3(matrix_num_x) / denom; - c.y = arcDeterminant3x3(matrix_num_y) / denom; /* Radius */ - r = sqrt((p1->x-c.x) * (p1->x-c.x) + (p1->y-c.y) * (p1->y-c.y)); + dx21 = p2->x - p1->x; + dy21 = p2->y - p1->y; + dx31 = p3->x - p1->x; + dy31 = p3->y - p1->y; + + h21 = pow(dx21, 2.0) + pow(dy21, 2.0); + h31 = pow(dx31, 2.0) + pow(dy31, 2.0); + + /* 2 * |Cross product|, d<0 means clockwise and d>0 counterclockwise sweeping angle */ + d = 2 * (dx21 * dy31 - dx31 * dy21); + + c.x = p1->x + (h21 * dy31 - h31 * dy21) / d; + c.y = p1->y - (h21 * dx31 - h31 * dx21) / d; + r = sqrt(pow(c.x - p1->x, 2) + pow(c.y - p1->y, 2)); } if ( radius ) *radius = r; @@ -1394,7 +1359,7 @@ int msPostGISParseData(layerObj *layer) } else { slength = strspn(pos_srid + 12, "-0123456789"); if (!slength) { - msSetError(MS_QUERYERR, "Error parsing PostGIS DATA variable. You specified 'USING SRID' but didnt have any numbers! %s", "msPostGISParseData()", data); + msSetError(MS_QUERYERR, "Error parsing PostGIS DATA variable. You specified 'USING SRID' but didn't have any numbers! %s", "msPostGISParseData()", data); return MS_FAILURE; } else { layerinfo->srid = (char*) msSmallMalloc(slength + 1); @@ -2487,7 +2452,6 @@ int msPostGISLayerOpen(layerObj *layer) * times there will be a leak... */ return MS_FAILURE; } - } } @@ -3489,7 +3453,7 @@ char *msPostGISEscapeSQLParam(layerObj *layer, const char *pszString) size_t nSrcLen; char* pszEscapedStr =NULL; - if (layer && pszString && strlen(pszString) > 0) { + if (layer && pszString) { if(!msPostGISLayerIsOpen(layer)) msPostGISLayerOpen(layer); @@ -3672,9 +3636,13 @@ int msPostGISLayerTranslateFilter(layerObj *layer, expressionObj *filter, char * native_string = msStringConcatenate(native_string, "FALSE"); break; case MS_TOKEN_LITERAL_NUMBER: - strtmpl = "%lf"; - snippet = (char *) msSmallMalloc(strlen(strtmpl) + 16); - sprintf(snippet, strtmpl, node->tokenval.dblval); + snippet = (char *) msSmallMalloc(32); + if( node->tokenval.dblval >= INT_MIN && + node->tokenval.dblval <= INT_MAX && + node->tokenval.dblval == (int)node->tokenval.dblval ) + sprintf(snippet, "%d", (int)node->tokenval.dblval); + else + sprintf(snippet, "%.18g", node->tokenval.dblval); native_string = msStringConcatenate(native_string, snippet); msFree(snippet); break; @@ -3785,7 +3753,15 @@ int msPostGISLayerTranslateFilter(layerObj *layer, expressionObj *filter, char * default: /* by default accept the general token to string conversion */ + if(node->token == MS_TOKEN_COMPARISON_EQ && node->next != NULL && node->next->token == MS_TOKEN_LITERAL_TIME) break; /* skip, handled with the next token */ if(bindingToken == MS_TOKEN_BINDING_TIME && (node->token == MS_TOKEN_COMPARISON_EQ || node->token == MS_TOKEN_COMPARISON_NE)) break; /* skip, handled elsewhere */ + if(node->token == MS_TOKEN_COMPARISON_EQ && node->next != NULL && node->next->token == MS_TOKEN_LITERAL_STRING && + strcmp(node->next->tokenval.strval, "_MAPSERVER_NULL_") == 0 ) + { + native_string = msStringConcatenate(native_string, " IS NULL"); + node = node->next; + break; + } native_string = msStringConcatenate(native_string, msExpressionTokenToString(node->token)); break; diff --git a/mapprimitive.c b/mapprimitive.c index 3d488d86c3..7b7f63b1d9 100644 --- a/mapprimitive.c +++ b/mapprimitive.c @@ -283,7 +283,17 @@ int *msGetInnerList(shapeObj *shape, int r, int *outerlist) continue; } - list[i] = msPointInPolygon(&(shape->line[i].point[0]), &(shape->line[r])); + /* A valid inner ring may touch its outer ring at most one point. */ + /* In the case the first point matches a vertex of an outer ring, */ + /* msPointInPolygon() might return 0 or 1 (depending on coordinate values, */ + /* see msGetOuterList()), so test a second point if the first test */ + /* returned that the point is not inside the outer ring. */ + /* Fixes #5299 */ + /* Of course all of this assumes that the geometries are indeed valid in */ + /* OGC terms, otherwise all logic of msIsOuterRing(), msGetOuterList(), */ + /* and msGetInnerList() has undefined behaviour. */ + list[i] = msPointInPolygon(&(shape->line[i].point[0]), &(shape->line[r])) || + msPointInPolygon(&(shape->line[i].point[1]), &(shape->line[r])); } return(list); @@ -1542,7 +1552,7 @@ void msPolylineComputeLineSegments(shapeObj *shape, struct polyline_lengths *pll pll->ll = msSmallMalloc(shape->numlines * sizeof(struct line_lengths)); pll->total_length = 0; - + pll->longest_line_index = 0; for(i=0; inumlines; i++) { diff --git a/mapproject.c b/mapproject.c index 1a10390be0..6a96660e9e 100644 --- a/mapproject.c +++ b/mapproject.c @@ -811,13 +811,32 @@ msProjectRectAsPolygon(projectionObj *in, projectionObj *out, double dx, dy; /* If projecting from longlat to projected */ + /* This hack was introduced for WFS 2.0 compliance testing, but is far */ + /* from being perfect */ if( out && !pj_is_latlong(out->proj) && in && pj_is_latlong(in->proj) && fabs(rect->minx - -180.0) < 1e-5 && fabs(rect->miny - -90.0) < 1e-5 && fabs(rect->maxx - 180.0) < 1e-5 && fabs(rect->maxy - 90.0) < 1e-5) { - rect->minx = -1e15; - rect->miny = -1e15; - rect->maxx = 1e15; - rect->maxy = 1e15; + pointObj pointTest; + pointTest.x = -180; + pointTest.y = 85; + msProjectPoint(in, out, &pointTest); + /* Detect if we are reprojecting from EPSG:4326 to EPSG:3857 */ + /* and if so use more plausible bounds to avoid issues with computed */ + /* resolution for WCS */ + if (fabs(pointTest.x - -20037508.3427892) < 1e-5 && fabs(pointTest.y - 19971868.8804086) ) + { + rect->minx = -20037508.3427892; + rect->miny = -20037508.3427892; + rect->maxx = 20037508.3427892; + rect->maxy = 20037508.3427892; + } + else + { + rect->minx = -1e15; + rect->miny = -1e15; + rect->maxx = 1e15; + rect->maxy = 1e15; + } return MS_SUCCESS; } @@ -930,7 +949,7 @@ msProjectRectAsPolygon(projectionObj *in, projectionObj *out, /* logic. */ /* -------------------------------------------------------------------- */ if( out && pj_is_latlong(out->proj) && in && !pj_is_latlong(in->proj) - && rect->maxx - rect->minx > 360.0 ) { + && rect->maxx - rect->minx > 360.0 && !out->gt.need_geotransform ) { rect->maxx = 180; rect->minx = -180; } @@ -942,6 +961,32 @@ msProjectRectAsPolygon(projectionObj *in, projectionObj *out, #endif } +/************************************************************************/ +/* msProjectHasLonWrap() */ +/************************************************************************/ + +int msProjectHasLonWrap(projectionObj *in, double* pdfLonWrap) +{ + int i; + if( pdfLonWrap ) + *pdfLonWrap = 0; +#if USE_PROJ + if( !pj_is_latlong(in->proj) ) + return MS_FALSE; +#endif + for( i = 0; i < in->numargs; i++ ) + { + if( strncmp(in->args[i], "lon_wrap=", + strlen("lon_wrap=")) == 0 ) + { + if( pdfLonWrap ) + *pdfLonWrap = atof(in->args[i] + strlen("lon_wrap=")); + return MS_TRUE; + } + } + return MS_FALSE; +} + /************************************************************************/ /* msProjectRect() */ /************************************************************************/ @@ -953,7 +998,52 @@ int msProjectRect(projectionObj *in, projectionObj *out, rectObj *rect) #else char *over = "+over"; int ret; + int bFreeInOver = MS_FALSE; + int bFreeOutOver = MS_FALSE; projectionObj in_over,out_over,*inp,*outp; + double dfLonWrap = 0.0; + +#if USE_PROJ + /* Detect projecting from north polar stereographic to longlat */ + if( in && !in->gt.need_geotransform && + out && !out->gt.need_geotransform && + !pj_is_latlong(in->proj) && pj_is_latlong(out->proj) ) + { + pointObj p; + p.x = 0.0; + p.y = 0.0; + if( msProjectPoint(in, out, &p) == MS_SUCCESS && + fabs(p.y - 90) < 1e-8 ) + { + /* Is the pole in the rectangle ? */ + if( 0 >= rect->minx && 0 >= rect->miny && + 0 <= rect->maxx && 0 <= rect->maxy ) + { + if( msProjectRectAsPolygon(in, out, rect ) == MS_SUCCESS ) + { + rect->minx = -180.0; + rect->maxx = 180.0; + rect->maxy = 90.0; + return MS_SUCCESS; + } + } + /* Are we sure the dateline is not enclosed ? */ + else if( rect->maxy < 0 || rect->maxx < 0 || rect->minx > 0 ) + { + return msProjectRectAsPolygon(in, out, rect ); + } + } + } +#endif + + if(in && msProjectHasLonWrap(in, &dfLonWrap) && dfLonWrap == 180.0) { + inp = in; + outp = out; + if( rect->maxx > 180.0 ) { + rect->minx = -180.0; + rect->maxx = 180.0; + } + } /* * Issue #4892: When projecting a rectangle we do not want proj to wrap resulting * coordinates around the dateline, as in practice a requested bounding box of @@ -963,24 +1053,28 @@ int msProjectRect(projectionObj *in, projectionObj *out, rectObj *rect) * To enforce this, we clone the input projections and add the "+over" proj * parameter in order to disable dateline wrapping. */ - if(out) { - msInitProjection(&out_over); - msCopyProjectionExtended(&out_over,out,&over,1); - outp = &out_over; - } else { - outp = out; - } - if(in) { - msInitProjection(&in_over); - msCopyProjectionExtended(&in_over,in,&over,1); - inp = &in_over; - } else { - inp = in; + else { + if(out) { + bFreeOutOver = MS_TRUE; + msInitProjection(&out_over); + msCopyProjectionExtended(&out_over,out,&over,1); + outp = &out_over; + } else { + outp = out; + } + if(in) { + bFreeInOver = MS_TRUE; + msInitProjection(&in_over); + msCopyProjectionExtended(&in_over,in,&over,1); + inp = &in_over; + } else { + inp = in; + } } ret = msProjectRectAsPolygon(inp,outp, rect ); - if(in) + if(bFreeInOver) msFreeProjection(&in_over); - if(out) + if(bFreeOutOver) msFreeProjection(&out_over); return ret; #endif @@ -1098,7 +1192,11 @@ int msProjectionsDiffer( projectionObj *proj1, projectionObj *proj2 ) int ret; ret = msProjectionsDifferInternal(proj1, proj2); - if( ret ) + if( ret && + /* to speed up things, do normalization only if one proj is */ + /* likely of the form init=epsg:XXX and the other proj=XXX datum=YYY... */ + ( (proj1->numargs == 1 && proj2->numargs > 1) || + (proj1->numargs > 1 && proj2->numargs == 1) ) ) { projectionObj* p1normalized; projectionObj* p2normalized; diff --git a/mapproject.h b/mapproject.h index 4204cc4389..c2966776ee 100644 --- a/mapproject.h +++ b/mapproject.h @@ -108,6 +108,8 @@ extern "C" { /*utility functions */ MS_DLL_EXPORT int GetMapserverUnitUsingProj(projectionObj *psProj); + + int msProjectHasLonWrap(projectionObj *in, double* pdfLonWrap); #endif #ifdef __cplusplus diff --git a/mapquery.c b/mapquery.c index a94ccb16e1..a0766911d6 100644 --- a/mapquery.c +++ b/mapquery.c @@ -670,8 +670,10 @@ int msQueryByFilter(mapObj *map) expressionObj old_filter; rectObj search_rect; + const rectObj invalid_rect = MS_INIT_INVALID_RECT; shapeObj shape; + int paging; int nclasses = 0; int *classgroup = NULL; @@ -731,12 +733,14 @@ int msQueryByFilter(mapObj *map) if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue; } + paging = msLayerGetPaging(lp); msLayerClose(lp); /* reset */ status = msLayerOpen(lp); if(status != MS_SUCCESS) goto query_error; + msLayerEnablePaging(lp, paging); /* disable driver paging */ - msLayerEnablePaging(lp, MS_FALSE); + // msLayerEnablePaging(lp, MS_FALSE); old_filteritem = lp->filteritem; /* cache the existing filter/filteritem */ msInitExpression(&old_filter); @@ -761,9 +765,10 @@ int msQueryByFilter(mapObj *map) if(status != MS_SUCCESS) goto query_error; search_rect = map->query.rect; + #ifdef USE_PROJ lp->project = msProjectionsDiffer(&(lp->projection), &(map->projection)); - if(lp->project) + if(lp->project && memcmp( &search_rect, &invalid_rect, sizeof(search_rect) ) != 0 ) msProjectRect(&(map->projection), &(lp->projection), &search_rect); /* project the searchrect to source coords */ #endif @@ -813,7 +818,7 @@ int msQueryByFilter(mapObj *map) #endif /* Should we skip this feature? */ - if (!msLayerGetPaging(lp) && map->query.startindex > 1) { + if (!paging && map->query.startindex > 1) { --map->query.startindex; msFreeShape(&shape); continue; @@ -876,6 +881,7 @@ int msQueryByRect(mapObj *map) char status; shapeObj shape, searchshape; rectObj searchrect, searchrectInMapProj; + const rectObj invalid_rect = MS_INIT_INVALID_RECT; double layer_tolerance = 0, tolerance = 0; int paging; @@ -977,7 +983,8 @@ int msQueryByRect(mapObj *map) #ifdef USE_PROJ lp->project = msProjectionsDiffer(&(lp->projection), &(map->projection)); - if(lp->project) + if(lp->project && + memcmp( &searchrect, &invalid_rect, sizeof(searchrect) ) != 0 ) msProjectRect(&(map->projection), &(lp->projection), &searchrect); /* project the searchrect to source coords */ #endif diff --git a/mapraster.c b/mapraster.c index 740b9af30f..1d6111eb4b 100644 --- a/mapraster.c +++ b/mapraster.c @@ -60,7 +60,7 @@ extern parseResultObj yypresult; /* result of parsing, true/false */ /* msGetClass_String() */ /************************************************************************/ -static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixel_value ) +static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixel_value, int firstClassToTry ) { int i; @@ -80,9 +80,18 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe /* Setup values list for expressions. */ /* -------------------------------------------------------------------- */ numitems = 4; - sprintf( red_value, "%d", color->red ); - sprintf( green_value, "%d", color->green ); - sprintf( blue_value, "%d", color->blue ); + if( color->red == -1 && color->green == -1 && color->blue == -1 ) + { + strcpy(red_value, "-1"); + strcpy(green_value, "-1"); + strcpy(blue_value, "-1"); + } + else + { + sprintf( red_value, "%d", color->red ); + sprintf( green_value, "%d", color->green ); + sprintf( blue_value, "%d", color->blue ); + } item_values[0] = (char *)pixel_value; item_values[1] = red_value; @@ -92,18 +101,24 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe /* -------------------------------------------------------------------- */ /* Loop over classes till we find a match. */ /* -------------------------------------------------------------------- */ - for(i=0; inumclasses; i++) { + for(i= (firstClassToTry < 0 ) ? 0 : -1; inumclasses; i++) { + + int idx = i; + if( i < 0 ) + idx = firstClassToTry; + else if( i == firstClassToTry ) + continue; /* check for correct classgroup, if set */ - if ( layer->class[i]->group && layer->classgroup && - strcasecmp(layer->class[i]->group, layer->classgroup) != 0 ) + if ( layer->class[idx]->group && layer->classgroup && + strcasecmp(layer->class[idx]->group, layer->classgroup) != 0 ) continue; /* Empty expression - always matches */ - if (layer->class[i]->expression.string == NULL) + if (layer->class[idx]->expression.string == NULL) return(i); - switch(layer->class[i]->expression.type) { + switch(layer->class[idx]->expression.type) { /* -------------------------------------------------------------------- */ /* Simple string match */ @@ -114,22 +129,22 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe while( *tmpstr1 == ' ' ) tmpstr1++; - if(strcmp(layer->class[i]->expression.string, tmpstr1) == 0) return(i); /* matched */ + if(strcmp(layer->class[idx]->expression.string, tmpstr1) == 0) return(idx); /* matched */ break; /* -------------------------------------------------------------------- */ /* Regular expression. Rarely used for raster. */ /* -------------------------------------------------------------------- */ case(MS_REGEX): - if(!layer->class[i]->expression.compiled) { - if(ms_regcomp(&(layer->class[i]->expression.regex), layer->class[i]->expression.string, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { /* compile the expression */ + if(!layer->class[idx]->expression.compiled) { + if(ms_regcomp(&(layer->class[idx]->expression.regex), layer->class[idx]->expression.string, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { /* compile the expression */ msSetError(MS_REGEXERR, "Invalid regular expression.", "msGetClass()"); return(-1); } - layer->class[i]->expression.compiled = MS_TRUE; + layer->class[idx]->expression.compiled = MS_TRUE; } - if(ms_regexec(&(layer->class[i]->expression.regex), pixel_value, 0, NULL, 0) == 0) return(i); /* got a match */ + if(ms_regexec(&(layer->class[idx]->expression.regex), pixel_value, 0, NULL, 0) == 0) return(idx); /* got a match */ break; /* -------------------------------------------------------------------- */ @@ -139,7 +154,7 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe int status; parseObj p; shapeObj dummy_shape; - expressionObj *expression = &(layer->class[i]->expression); + expressionObj *expression = &(layer->class[idx]->expression); dummy_shape.numvalues = numitems; dummy_shape.values = item_values; @@ -160,7 +175,7 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe } if( p.result.intval ) - return i; + return idx; break; } } @@ -179,7 +194,7 @@ int msGetClass(layerObj *layer, colorObj *color, int colormap_index) snprintf( pixel_value, sizeof(pixel_value), "%d", colormap_index ); - return msGetClass_String( layer, color, pixel_value ); + return msGetClass_String( layer, color, pixel_value, -1 ); } /************************************************************************/ @@ -190,6 +205,13 @@ int msGetClass(layerObj *layer, colorObj *color, int colormap_index) /************************************************************************/ int msGetClass_FloatRGB(layerObj *layer, float fValue, int red, int green, int blue ) +{ + return msGetClass_FloatRGB_WithFirstClassToTry( + layer, fValue, red, green, blue, -1); +} + + +int msGetClass_FloatRGB_WithFirstClassToTry(layerObj *layer, float fValue, int red, int green, int blue, int firstClassToTry ) { char pixel_value[100]; colorObj color; @@ -200,7 +222,7 @@ int msGetClass_FloatRGB(layerObj *layer, float fValue, int red, int green, int b snprintf( pixel_value, sizeof(pixel_value), "%18g", fValue ); - return msGetClass_String( layer, &color, pixel_value ); + return msGetClass_String( layer, &color, pixel_value, firstClassToTry ); } #if defined(USE_GDAL) @@ -668,14 +690,23 @@ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image, } if(layer->connectiontype != MS_KERNELDENSITY) { + char* pszPath; if(strlen(filename) == 0) continue; if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): Filename is: %s\n", layer->name, filename); - msDrawRasterBuildRasterPath(map, layer, filename, szPath); + if( strncmp(filename, "debug == MS_TRUE) - msDebug("msDrawRasterLayerLow(%s): Path is: %s\n", layer->name, szPath); + msDebug("msDrawRasterLayerLow(%s): Path is: %s\n", layer->name, pszPath); /* ** Note: because we do decryption after the above path expansion @@ -684,15 +715,17 @@ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image, ** components. But that is mostly ok, since stuff like sde,postgres and ** oracle georaster do not use real paths. */ - decrypted_path = msDecryptStringTokens( map, szPath ); + decrypted_path = msDecryptStringTokens( map, pszPath ); if( decrypted_path == NULL ) return MS_FAILURE; msAcquireLock( TLOCK_GDAL ); hDS = GDALOpenShared( decrypted_path, GA_ReadOnly ); } else { + msAcquireLock( TLOCK_GDAL ); status = msComputeKernelDensityDataset(map, image, layer, &hDS, &kernel_density_cleanup_ptr); if(status != MS_SUCCESS) { + msReleaseLock( TLOCK_GDAL ); final_status = status; goto cleanup; } @@ -702,6 +735,8 @@ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image, /* Set the projection to the map file projection */ if (msLoadProjectionString(&(layer->projection), mapProjStr) != 0) { + GDALClose( hDS ); + msReleaseLock( TLOCK_GDAL ); msSetError(MS_CGIERR, "Unable to set projection on interpolation layer.", "msDrawRasterLayerLow()"); return(MS_FAILURE); } @@ -745,6 +780,7 @@ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image, if( msDrawRasterLoadProjection(layer, hDS, filename, tilesrsindex, tilesrsname) != MS_SUCCESS ) { + GDALClose( hDS ); msReleaseLock( TLOCK_GDAL ); final_status = MS_FAILURE; break; @@ -792,18 +828,31 @@ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image, ** default to keeping open for single data files, and ** to closing for tile indexes */ - - close_connection = msLayerGetProcessingKey( layer, + if(layer->connectiontype == MS_KERNELDENSITY) { + /* + ** Fix issue #5330 + ** The in-memory kernel density heatmap gdal dataset handle (hDS) gets re-used + ** but the associated rasterband cache doesn't get flushed, which causes old data + ** to be rendered instead of the newly generated imagery. To fix, simply close the + ** the handle and prevent further re-use. + ** Note that instead of this workaround, we could explicitely set + ** CLOSE_CONNECTION=ALWAYS on the kerneldensity layer. + */ + GDALClose( hDS ); + } + else { + close_connection = msLayerGetProcessingKey( layer, "CLOSE_CONNECTION" ); - if( close_connection == NULL && layer->tileindex == NULL ) - close_connection = "DEFER"; + if( close_connection == NULL && layer->tileindex == NULL ) + close_connection = "DEFER"; - if( close_connection != NULL - && strcasecmp(close_connection,"DEFER") == 0 ) { - GDALDereferenceDataset( hDS ); - } else { - GDALClose( hDS ); + if( close_connection != NULL + && strcasecmp(close_connection,"DEFER") == 0 ) { + GDALDereferenceDataset( hDS ); + } else { + GDALClose( hDS ); + } } msReleaseLock( TLOCK_GDAL ); } /* next tile */ diff --git a/maprasterquery.c b/maprasterquery.c index b6556be0ed..ccf1528931 100644 --- a/maprasterquery.c +++ b/maprasterquery.c @@ -193,7 +193,7 @@ static void msRasterLayerInfoInitialize( layerObj *layer ) /* We need to do this or the layer->layerinfo will be interpreted */ /* as shapefile access info because the default connectiontype is */ /* MS_SHAPEFILE. */ - if (layer->connectiontype != MS_WMS) + if (layer->connectiontype != MS_WMS && layer->connectiontype != MS_KERNELDENSITY) layer->connectiontype = MS_RASTER; rlinfo->query_result_hard_max = 1000000; diff --git a/mapregex.c b/mapregex.c index 00eac84e49..6a8a74fa6b 100644 --- a/mapregex.c +++ b/mapregex.c @@ -45,7 +45,7 @@ /*Need to specify this so that mapregex.h doesn't defined constants and doesn't #define away our ms_*/ -#if defined(_WIN32) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) && _MSC_VER < 1900 #define off_t long #endif diff --git a/maprendering.c b/maprendering.c index 7ee3692691..4af4887bcd 100644 --- a/maprendering.c +++ b/maprendering.c @@ -996,6 +996,7 @@ int msDrawTextSymbol(mapObj *map, imageObj *image, pointObj labelPnt, textSymbol colorObj *c = NULL, *oc = NULL; int ow; assert(ts->textpath); + if(!renderer->renderGlyphs) return MS_FAILURE; if(!ts->textpath->absolute) { int g; @@ -1019,12 +1020,47 @@ int msDrawTextSymbol(mapObj *map, imageObj *image, pointObj labelPnt, textSymbol } } } + + if(MS_VALID_COLOR(ts->label->shadowcolor)) { + textSymbolObj *ts_shadow; + int g; + double ox, oy; + double cosa,sina; + int ret; + if(ts->rotation != 0) { + cosa = cos(ts->rotation); + sina = sin(ts->rotation); + ox = ts->scalefactor * (cosa * ts->label->shadowsizex + + sina * ts->label->shadowsizey); + oy = ts->scalefactor * (-sina * ts->label->shadowsizex + + cosa * ts->label->shadowsizey); + } + else { + ox = ts->scalefactor * ts->label->shadowsizex; + oy = ts->scalefactor * ts->label->shadowsizey; + } + + ts_shadow = msSmallMalloc(sizeof(textSymbolObj)); + initTextSymbol(ts_shadow); + msCopyTextSymbol(ts_shadow,ts); + + for(g=0;gtextpath->numglyphs;g++) { + ts_shadow->textpath->glyphs[g].pnt.x += ox; + ts_shadow->textpath->glyphs[g].pnt.y += oy; + } + + ret = renderer->renderGlyphs(image,ts_shadow->textpath,&ts->label->shadowcolor,NULL,0); + freeTextSymbol(ts_shadow); + msFree(ts_shadow); + if( ret != MS_SUCCESS ) + return ret; + } + if(MS_VALID_COLOR(ts->label->color)) c = &ts->label->color; 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)); - if(!renderer->renderGlyphs) return MS_FAILURE; return renderer->renderGlyphs(image,ts->textpath,c,oc,ow); } diff --git a/mapresample.c b/mapresample.c index 7107bcbc55..0bad1b2f5a 100644 --- a/mapresample.c +++ b/mapresample.c @@ -83,7 +83,8 @@ msNearestRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb, imageObj *psDstImage, rasterBufferObj *dst_rb, int *panCMap, SimpleTransformer pfnTransform, void *pCBData, - int debug, rasterBufferObj *mask_rb ) + int debug, rasterBufferObj *mask_rb, + int bWrapAtLeftRight ) { double *x, *y; @@ -122,6 +123,9 @@ msNearestRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb, nSrcX = (int) x[nDstX]; nSrcY = (int) y[nDstX]; + if( bWrapAtLeftRight && nSrcX >= nSrcXSize && nSrcX < 2 * nSrcXSize ) + nSrcX -= nSrcXSize; + /* * We test the original floating point values to * avoid errors related to asymmetric rounding around zero. @@ -302,7 +306,8 @@ msBilinearRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb, imageObj *psDstImage, rasterBufferObj *dst_rb, int *panCMap, SimpleTransformer pfnTransform, void *pCBData, - int debug, rasterBufferObj *mask_rb ) + int debug, rasterBufferObj *mask_rb, + int bWrapAtLeftRight ) { double *x, *y; @@ -359,31 +364,32 @@ msBilinearRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb, dfRatioY2 = y[nDstX] - nSrcY; /* If we are right off the source, skip this pixel */ - if( nSrcX2 < 0 || nSrcX >= nSrcXSize + if( nSrcX2 < 0 || (!bWrapAtLeftRight && nSrcX >= nSrcXSize) || nSrcY2 < 0 || nSrcY >= nSrcYSize ) continue; /* Trim in stuff one pixel off the edge */ nSrcX = MS_MAX(nSrcX,0); nSrcY = MS_MAX(nSrcY,0); - nSrcX2 = MS_MIN(nSrcX2,nSrcXSize-1); + if( !bWrapAtLeftRight ) + nSrcX2 = MS_MIN(nSrcX2,nSrcXSize-1); nSrcY2 = MS_MIN(nSrcY2,nSrcYSize-1); memset( padfPixelSum, 0, sizeof(double) * bandCount); - msSourceSample( psSrcImage, src_rb, nSrcX, nSrcY, padfPixelSum, + msSourceSample( psSrcImage, src_rb, nSrcX % nSrcXSize, nSrcY, padfPixelSum, (1.0 - dfRatioX2) * (1.0 - dfRatioY2), &dfWeightSum ); - msSourceSample( psSrcImage, src_rb, nSrcX2, nSrcY, padfPixelSum, + msSourceSample( psSrcImage, src_rb, nSrcX2 % nSrcXSize, nSrcY, padfPixelSum, (dfRatioX2) * (1.0 - dfRatioY2), &dfWeightSum ); - msSourceSample( psSrcImage, src_rb, nSrcX, nSrcY2, padfPixelSum, + msSourceSample( psSrcImage, src_rb, nSrcX % nSrcXSize, nSrcY2, padfPixelSum, (1.0 - dfRatioX2) * (dfRatioY2), &dfWeightSum ); - msSourceSample( psSrcImage, src_rb, nSrcX2, nSrcY2, padfPixelSum, + msSourceSample( psSrcImage, src_rb, nSrcX2 % nSrcXSize, nSrcY2, padfPixelSum, (dfRatioX2) * (dfRatioY2), &dfWeightSum ); @@ -1123,6 +1129,115 @@ static int msTransformMapToSource( int nDstXSize, int nDstYSize, } } + /* -------------------------------------------------------------------- */ + /* Deal with discontinuities related to lon_wrap=XXX in source */ + /* projection. In that case we must check if the points at */ + /* lon_wrap +/- 180deg are in the output raster. */ + /* -------------------------------------------------------------------- */ + if( bOutInit && pj_is_latlong(psSrcProj->proj) ) + { + double dfLonWrap = 0; + int bHasLonWrap = msProjectHasLonWrap(psSrcProj, &dfLonWrap); + + if( bHasLonWrap ) + { + double x2[2], y2[2], z2[2]; + int nCountY = 0; + double dfY = 0.0; + double dfXMinOut = 0.0; + double dfYMinOut = 0.0; + double dfXMaxOut = 0.0; + double dfYMaxOut = 0.0; + + /* Find out average y coordinate in src projection */ + for( i = 0; i < nSamples; i++ ) { + if( y[i] != HUGE_VAL ) { + dfY += y[i]; + nCountY ++; + } + } + dfY /= nCountY; + + /* Compute bounds of output raster */ + for( i = 0; i < 4; i ++ ) + { + double dfX = adfDstGeoTransform[0] + + ((i == 1 || i == 2) ? nDstXSize : 0) * adfDstGeoTransform[1] + + ((i == 1 || i == 3 ) ? nDstYSize : 0) * adfDstGeoTransform[2]; + double dfY = adfDstGeoTransform[3] + + ((i == 1 || i == 2) ? nDstXSize : 0) * adfDstGeoTransform[4] + + ((i == 1 || i == 3 ) ? nDstYSize : 0) * adfDstGeoTransform[5]; + if( i == 0 || dfX < dfXMinOut ) dfXMinOut = dfX; + if( i == 0 || dfY < dfYMinOut ) dfYMinOut = dfY; + if( i == 0 || dfX > dfXMaxOut ) dfXMaxOut = dfX; + if( i == 0 || dfY > dfYMaxOut ) dfYMaxOut = dfY; + } + + x2[0] = dfLonWrap-180+1e-7; + y2[0] = dfY; + z2[0] = 0.0; + + x2[1] = dfLonWrap+180-1e-7; + y2[1] = dfY; + z2[1] = 0.0; + + msAcquireLock( TLOCK_PROJ ); + pj_transform( psSrcProj->proj, psDstProj->proj, + 2, 1, x2, y2, z2 ); + msReleaseLock( TLOCK_PROJ ); + + if( x2[0] >= dfXMinOut && x2[0] <= dfXMaxOut && + y2[0] >= dfYMinOut && y2[0] <= dfYMaxOut ) + { + double x_out = adfInvSrcGeoTransform[0] + + (dfLonWrap-180)*adfInvSrcGeoTransform[1] + + dfY*adfInvSrcGeoTransform[2]; + double y_out = adfInvSrcGeoTransform[3] + + (dfLonWrap-180)*adfInvSrcGeoTransform[4] + + dfY*adfInvSrcGeoTransform[5]; + + /* Does the raster cover a whole 360 deg range ? */ + if( nSrcXSize == (int)(adfInvSrcGeoTransform[1] * 360 + 0.5) ) + { + psSrcExtent->minx = 0; + psSrcExtent->maxx = nSrcXSize; + } + else + { + psSrcExtent->minx = MS_MIN(psSrcExtent->minx, x_out); + psSrcExtent->maxx = MS_MAX(psSrcExtent->maxx, x_out); + } + psSrcExtent->miny = MS_MIN(psSrcExtent->miny, y_out); + psSrcExtent->maxy = MS_MAX(psSrcExtent->maxy, y_out); + } + + if( x2[1] >= dfXMinOut && x2[1] <= dfXMaxOut && + x2[1] >= dfYMinOut && y2[1] <= dfYMaxOut ) + { + double x_out = adfInvSrcGeoTransform[0] + + (dfLonWrap+180)*adfInvSrcGeoTransform[1] + + dfY*adfInvSrcGeoTransform[2]; + double y_out = adfInvSrcGeoTransform[3] + + (dfLonWrap+180)*adfInvSrcGeoTransform[4] + + dfY*adfInvSrcGeoTransform[5]; + + /* Does the raster cover a whole 360 deg range ? */ + if( nSrcXSize == (int)(adfInvSrcGeoTransform[1] * 360 + 0.5) ) + { + psSrcExtent->minx = 0; + psSrcExtent->maxx = nSrcXSize; + } + else + { + psSrcExtent->minx = MS_MIN(psSrcExtent->minx, x_out); + psSrcExtent->maxx = MS_MAX(psSrcExtent->maxx, x_out); + } + psSrcExtent->miny = MS_MIN(psSrcExtent->miny, y_out); + psSrcExtent->maxy = MS_MAX(psSrcExtent->maxy, y_out); + } + } + } + if( !bOutInit ) return MS_FALSE; @@ -1181,6 +1296,7 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image, double dfOversampleRatio; rasterBufferObj src_rb, *psrc_rb = NULL, *mask_rb = NULL; int bAddPixelMargin = MS_TRUE; + int bWrapAtLeftRight = MS_FALSE; const char *resampleMode = CSLFetchNameValue( layer->processing, @@ -1240,14 +1356,47 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image, /* -------------------------------------------------------------------- */ if( CSLFetchBoolean( layer->processing, "LOAD_WHOLE_IMAGE", FALSE ) ) bSuccess = FALSE; - else + else { bSuccess = msTransformMapToSource( nDstXSize, nDstYSize, adfDstGeoTransform, &(map->projection), nSrcXSize, nSrcYSize,adfInvSrcGeoTransform, &(layer->projection), &sSrcExtent, FALSE ); - + if (bSuccess) { + /* -------------------------------------------------------------------- */ + /* Repeat transformation for a rectangle interior to the output */ + /* requested region. If the latter results in a more extreme y */ + /* extent, then extend extents in source layer projection to */ + /* southern/northing bounds and entire x extent. */ + /* -------------------------------------------------------------------- */ + memcpy( &sOrigSrcExtent, &sSrcExtent, sizeof(sSrcExtent) ); + adfDstGeoTransform[0] = adfDstGeoTransform[0] + adfDstGeoTransform[1]; + adfDstGeoTransform[3] = adfDstGeoTransform[3] + adfDstGeoTransform[5]; + bSuccess = + msTransformMapToSource( nDstXSize-2, nDstYSize-2, adfDstGeoTransform, + &(map->projection), + nSrcXSize, nSrcYSize,adfInvSrcGeoTransform, + &(layer->projection), + &sSrcExtent, FALSE ); + /* Reset this array to its original value! */ + memcpy( adfDstGeoTransform, map->gt.geotransform, sizeof(double)*6 ); + + if (bSuccess) { + if (sSrcExtent.maxy > sOrigSrcExtent.maxy || sSrcExtent.miny < sOrigSrcExtent.miny) { + msDebug( "msTransformMapToSource(): extending bounds.\n"); + sOrigSrcExtent.minx = 0; + sOrigSrcExtent.maxx = nSrcXSize; + if (sSrcExtent.maxy > sOrigSrcExtent.maxy) + sOrigSrcExtent.maxy = nSrcYSize; + if (sSrcExtent.miny < sOrigSrcExtent.miny) + sOrigSrcExtent.miny = 0; + } + } + memcpy( &sSrcExtent, &sOrigSrcExtent, sizeof(sOrigSrcExtent) ); + bSuccess = TRUE; + } + } /* -------------------------------------------------------------------- */ /* If the transformation failed, it is likely that we have such */ /* broad extents that the projection transformation failed at */ @@ -1370,7 +1519,16 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image, sqrt(adfSrcGeoTransform[1] * adfSrcGeoTransform[1] + adfSrcGeoTransform[2] * adfSrcGeoTransform[2]); - if( (sOrigSrcExtent.maxx - sOrigSrcExtent.minx) > dfOversampleRatio * nDstXSize + /* Check first that the requested extent is not well beyond than the source */ + /* raster. This might be the case for example if asking to visualize */ + /* -180,-89,180,90 in EPSG:4326 from a raster in Arctic Polar Stereographic */ + /* But restrict that to rasters of modest size, otherwise we may end up */ + /* requesting very large dimensions in other legit reprojection cases */ + /* See https://github.com/mapserver/mapserver/issues/5402 */ + if( !(sOrigSrcExtent.minx <= -4 * nSrcXSize && sOrigSrcExtent.miny <= -4 * nSrcYSize && + sOrigSrcExtent.maxx >= 5 * nSrcXSize && sOrigSrcExtent.maxy >= 5 * nSrcYSize && + nSrcXSize < 4000 && nSrcYSize < 4000) + && (sOrigSrcExtent.maxx - sOrigSrcExtent.minx) > dfOversampleRatio * nDstXSize && !CSLFetchBoolean( layer->processing, "LOAD_FULL_RES_IMAGE", FALSE )) sDummyMap.cellsize = (dfNominalCellSize * (sOrigSrcExtent.maxx - sOrigSrcExtent.minx)) @@ -1408,6 +1566,23 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image, adfSrcGeoTransform[4] *= (sDummyMap.cellsize / dfNominalCellSize); adfSrcGeoTransform[5] *= (sDummyMap.cellsize / dfNominalCellSize); + /* In the non-rotated case, make sure that the geotransform exactly */ + /* matches the sSrcExtent, even if that generates non-square pixels (#1715) */ + /* The rotated case should ideally be dealt with, but not for now... */ + if( adfSrcGeoTransform[2] == 0 && adfSrcGeoTransform[4] == 0 && + adfSrcGeoTransform[5] < 0 && + /* But do that only if the pixels were square before, otherwise */ + /* this is going to mess with source rasters whose pixels aren't at */ + /* all square (#5445) */ + fabs(fabs(adfSrcGeoTransform[1]) - fabs(adfSrcGeoTransform[5])) < + 0.01 * fabs(adfSrcGeoTransform[1]) ) + { + adfSrcGeoTransform[1] = (sSrcExtent.maxx - sSrcExtent.minx) * + dfNominalCellSize / nLoadImgXSize; + adfSrcGeoTransform[5] = -(sSrcExtent.maxy - sSrcExtent.miny) * + dfNominalCellSize / nLoadImgYSize; + } + papszAlteredProcessing = CSLDuplicate( layer->processing ); papszAlteredProcessing = CSLSetNameValue( papszAlteredProcessing, "RAW_WINDOW", @@ -1528,6 +1703,13 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image, /* -------------------------------------------------------------------- */ pACBData = msInitApproxTransformer( msProjTransformer, pTCBData, 0.333 ); + if( pj_is_latlong(layer->projection.proj) ) + { + /* Does the raster cover a whole 360 deg range ? */ + if( nSrcXSize == (int)(adfInvSrcGeoTransform[1] * 360 + 0.5) ) + bWrapAtLeftRight = MS_TRUE; + } + /* -------------------------------------------------------------------- */ /* Perform the resampling. */ /* -------------------------------------------------------------------- */ @@ -1540,12 +1722,12 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image, result = msBilinearRasterResampler( srcImage, psrc_rb, image, rb, anCMap, msApproxTransformer, pACBData, - layer->debug, mask_rb ); + layer->debug, mask_rb, bWrapAtLeftRight ); else result = msNearestRasterResampler( srcImage, psrc_rb, image, rb, anCMap, msApproxTransformer, pACBData, - layer->debug, mask_rb ); + layer->debug, mask_rb, bWrapAtLeftRight ); /* -------------------------------------------------------------------- */ /* cleanup */ diff --git a/mapscript/csharp/CMakeLists.txt b/mapscript/csharp/CMakeLists.txt index 27a28b99e5..b2792f4a86 100644 --- a/mapscript/csharp/CMakeLists.txt +++ b/mapscript/csharp/CMakeLists.txt @@ -21,6 +21,10 @@ if (WIN32) if (MSVC_VERSION GREATER 1500) set(PLATFORM_TARGET ${PLATFORM_TARGET} /define:CLR4) endif (MSVC_VERSION GREATER 1500) + MESSAGE(STATUS "Cmake build type: ${CMAKE_BUILD_TYPE}") + if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + set(PLATFORM_TARGET ${PLATFORM_TARGET} /debug:full) + endif (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") endif(WIN32) MARK_AS_ADVANCED(CSHARP_COMPILER) @@ -40,8 +44,10 @@ SWIG_LINK_LIBRARIES(csharpmapscript ${MAPSERVER_LIBMAPSERVER}) ADD_CUSTOM_COMMAND(TARGET csharpmapscript WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} POST_BUILD - COMMAND copy /Y ..\\..\\..\\mapscript\\csharp\\mapscript.snk - COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /t:library /out:mapscript_csharp.dll ${KEYFILE_SPEC} *.cs ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\config\\AssemblyInfo.cs + COMMAND set MAPSCRIPT_SNK=${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\mapscript.snk + COMMAND set MAPSCRIPT_SNK=%MAPSCRIPT_SNK:/=\\% + COMMAND copy /Y \"%MAPSCRIPT_SNK%\" + COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /t:library /out:mapscript_csharp.dll ${KEYFILE_SPEC} *.cs ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\config\\AssemblyInfo.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:shpdump.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\shpdump.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:drawmap.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmap.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:shapeinfo.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\shapeinfo.cs @@ -50,7 +56,9 @@ ADD_CUSTOM_COMMAND(TARGET csharpmapscript COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:HTMLtemplate.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\HTMLtemplate.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:RFC24.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\RFC24.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirect.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapDirect.cs - COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirectPrint.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapDirectPrint.cs + COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirectPrint.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapDirectPrint.cs + COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapGDIPlus.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapGDIPlus.cs + #COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /lib:C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF /r:mapscript_csharp.dll /r:System.Xaml.dll /r:WindowsBase.dll /r:PresentationCore.dll /out:drawmapWPF.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapWPF.cs COMMENT "Compiling c# source files" ) diff --git a/mapscript/csharp/Makefile.vc b/mapscript/csharp/Makefile.vc index 9fdc747a5b..2297b8889c 100755 --- a/mapscript/csharp/Makefile.vc +++ b/mapscript/csharp/Makefile.vc @@ -95,7 +95,8 @@ $(CSHARP_DLL):: $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:HTMLtemplate.exe examples\HTMLtemplate.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:RFC24.exe examples\RFC24.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirect.exe examples\drawmapDirect.cs - $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirectPrint.exe examples\drawmapDirectPrint.cs + $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirectPrint.exe examples\drawmapDirectPrint.cs + $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapGDIPlus.exe examples\drawmapGDIPlus.cs test: !IFDEF MONO diff --git a/mapscript/csharp/csmodule.i b/mapscript/csharp/csmodule.i index 3bf2650e9c..6a9836a7f2 100644 --- a/mapscript/csharp/csmodule.i +++ b/mapscript/csharp/csmodule.i @@ -241,6 +241,11 @@ static SWIG_CSharpByteArrayHelperCallback SWIG_csharp_bytearray_callback = NULL; %typemap(in) SWIG_CSharpByteArrayHelperCallback %{ $1 = ($1_ltype)$input; %} %typemap(csin) SWIG_CSharpByteArrayHelperCallback "$csinput" +%typemap(imtype) (unsigned char* pixels) "IntPtr" +%typemap(cstype) (unsigned char* pixels) "IntPtr" +%typemap(in) (unsigned char* pixels) %{ $1 = ($1_ltype)$input; %} +%typemap(csin) (unsigned char* pixels) "$csinput" + %csmethodmodifiers getBytes "private"; %ignore imageObj::getBytes(); %extend imageObj @@ -259,7 +264,26 @@ static SWIG_CSharpByteArrayHelperCallback SWIG_csharp_bytearray_callback = NULL; } callback(buffer.data, buffer.size); msFree(buffer.data); - } + } + + int getRawPixels(unsigned char* pixels) { + if (MS_RENDERER_PLUGIN(self->format)) { + rendererVTableObj *renderer = self->format->vtable; + if(renderer->supports_pixel_buffer) { + rasterBufferObj rb; + int status = MS_SUCCESS; + int size = self->width * self->height * 4 * sizeof(unsigned char); + + status = renderer->getRasterBufferHandle(self,&rb); + if(UNLIKELY(status == MS_FAILURE)) { + return MS_FAILURE; + } + memcpy(pixels, rb.data.rgba.pixels, size); + return status; + } + } + return MS_FAILURE; + } } %ignore imageObj::write; @@ -406,6 +430,12 @@ DllExport void SWIGSTDCALL SWIGRegisterByteArrayCallback_$module(SWIG_CSharpByte %} %typemap(csvarin, excode="") (double pattern[ANY]) %{$excode%} +/* Typemaps for int array */ +%typemap(imtype, out="IntPtr") int *panIndexes "int[]" +%typemap(cstype) int *panIndexes %{int[]%} +%typemap(in) int *panIndexes %{ $1 = ($1_ltype)$input; %} +%typemap(csin) (int *panIndexes) "$csinput" + /* Typemaps for device handle */ %typemap(imtype) (void* device) %{IntPtr%} %typemap(cstype) (void* device) %{IntPtr%} diff --git a/mapscript/csharp/examples/drawmapGDIPlus.cs b/mapscript/csharp/examples/drawmapGDIPlus.cs new file mode 100644 index 0000000000..c08ccd2b1a --- /dev/null +++ b/mapscript/csharp/examples/drawmapGDIPlus.cs @@ -0,0 +1,97 @@ +/****************************************************************************** + * $Id$ + * + * Project: MapServer + * Purpose: A C# based mapscript example to draw the map directly onto a GDI+ bitmap. + * Author: Tamas Szekeres, szekerest@gmail.com + * + ****************************************************************************** + * Copyright (c) 1996-2008 Regents of the University of Minnesota. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies of this Software or works derived from this Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + *****************************************************************************/ + +using System; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using OSGeo.MapServer; + +/// +/// A C# based mapscript example to draw the map directly onto a GDI+ bitmap. +/// +class DrawMap +{ + public static void usage() + { + Console.WriteLine("usage: DrawMapGDIPlus {mapfile} {outfile}"); + System.Environment.Exit(-1); + } + + public static void Main(string[] args) + { + Console.WriteLine(""); + if (args.Length < 2) usage(); + + mapObj map = new mapObj(args[0]); + + Console.WriteLine("# Map layers " + map.numlayers + "; Map name = " + map.name); + for (int i = 0; i < map.numlayers; i++) + { + Console.WriteLine("Layer [" + i + "] name: " + map.getLayer(i).name); + } + + try + { + Bitmap mapImage = new Bitmap(map.width, map.height, PixelFormat.Format32bppRgb); + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + using (imageObj image = map.draw()) + { + BitmapData bitmapData = mapImage.LockBits(new Rectangle(0, 0, image.width, image.height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb); + try + { + if (image.getRawPixels(bitmapData.Scan0) == (int)MS_RETURN_VALUE.MS_FAILURE) + { + Console.WriteLine("Unable to get image contents"); + } + } + finally + { + mapImage.UnlockBits(bitmapData); + } + + Console.WriteLine("Rendering time: " + stopwatch.ElapsedMilliseconds + "ms"); + + mapImage.Save(args[1]); + } + } + catch (Exception ex) + { + Console.WriteLine( "\nMessage ---\n{0}", ex.Message ); + Console.WriteLine( + "\nHelpLink ---\n{0}", ex.HelpLink ); + Console.WriteLine( "\nSource ---\n{0}", ex.Source ); + Console.WriteLine( + "\nStackTrace ---\n{0}", ex.StackTrace ); + Console.WriteLine( + "\nTargetSite ---\n{0}", ex.TargetSite ); } + } +} + diff --git a/mapscript/csharp/examples/drawmapWPF.cs b/mapscript/csharp/examples/drawmapWPF.cs new file mode 100644 index 0000000000..2e6e833615 --- /dev/null +++ b/mapscript/csharp/examples/drawmapWPF.cs @@ -0,0 +1,109 @@ +/****************************************************************************** + * $Id$ + * + * Project: MapServer + * Purpose: A C# based mapscript example to draw the map directly onto a WPF image. + * Author: Tamas Szekeres, szekerest@gmail.com + * + ****************************************************************************** + * Copyright (c) 1996-2008 Regents of the University of Minnesota. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies of this Software or works derived from this Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + *****************************************************************************/ + +using System; +using System.IO; +using System.Diagnostics; +using System.Windows; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using OSGeo.MapServer; + +/// +/// A C# based mapscript example to draw the map directly onto a WPF image. +/// +class DrawMap +{ + public static void usage() + { + Console.WriteLine("usage: DrawMapWPF {mapfile} {outfile}"); + System.Environment.Exit(-1); + } + + public static void Main(string[] args) + { + Console.WriteLine(""); + if (args.Length < 2) usage(); + + mapObj map = new mapObj(args[0]); + + Console.WriteLine("# Map layers " + map.numlayers + "; Map name = " + map.name); + for (int i = 0; i < map.numlayers; i++) + { + Console.WriteLine("Layer [" + i + "] name: " + map.getLayer(i).name); + } + + try + { + WriteableBitmap mapImage = new WriteableBitmap(map.width, map.height, 96, 96, PixelFormats.Bgr32, null); + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + using (imageObj image = map.draw()) + { + // Reserve the back buffer for updates. + mapImage.Lock(); + try + { + if (image.getRawPixels(mapImage.BackBuffer) == (int)MS_RETURN_VALUE.MS_FAILURE) + { + Console.WriteLine("Unable to get image contents"); + } + // Specify the area of the bitmap that changed. + mapImage.AddDirtyRect(new Int32Rect(0, 0, map.width, map.height)); + } + finally + { + // Release the back buffer and make it available for display. + mapImage.Unlock(); + } + + Console.WriteLine("Rendering time: " + stopwatch.ElapsedMilliseconds + "ms"); + + // Save the bitmap into a file. + using (FileStream stream = new FileStream(args[1], FileMode.Create)) + { + PngBitmapEncoder encoder = new PngBitmapEncoder(); + encoder.Frames.Add(BitmapFrame.Create(mapImage)); + encoder.Save(stream); + } + } + } + catch (Exception ex) + { + Console.WriteLine( "\nMessage ---\n{0}", ex.Message ); + Console.WriteLine( + "\nHelpLink ---\n{0}", ex.HelpLink ); + Console.WriteLine( "\nSource ---\n{0}", ex.Source ); + Console.WriteLine( + "\nStackTrace ---\n{0}", ex.StackTrace ); + Console.WriteLine( + "\nTargetSite ---\n{0}", ex.TargetSite ); } + } +} + diff --git a/mapscript/csharp/swig_csharp_extensions.i b/mapscript/csharp/swig_csharp_extensions.i index 07b8b8dbc1..75f439917d 100644 --- a/mapscript/csharp/swig_csharp_extensions.i +++ b/mapscript/csharp/swig_csharp_extensions.i @@ -33,8 +33,58 @@ %pragma(csharp) imclasscode=%{ static $imclassname() { } + + public class UTF8Marshaler : ICustomMarshaler { + static UTF8Marshaler static_instance; + + public IntPtr MarshalManagedToNative(object managedObj) { + if (managedObj == null) + return IntPtr.Zero; + if (!(managedObj is string)) + throw new MarshalDirectiveException( + "UTF8Marshaler must be used on a string."); + + // not null terminated + byte[] strbuf = System.Text.Encoding.UTF8.GetBytes((string)managedObj); + IntPtr buffer = Marshal.AllocHGlobal(strbuf.Length + 1); + Marshal.Copy(strbuf, 0, buffer, strbuf.Length); + + // write the terminating null + Marshal.WriteByte(buffer, strbuf.Length, 0); + return buffer; + } + + public object MarshalNativeToManaged(IntPtr pNativeData) { + int len = Marshal.PtrToStringAnsi(pNativeData).Length; + byte[] utf8data = new byte[len]; + Marshal.Copy(pNativeData, utf8data, 0, len); + return System.Text.Encoding.UTF8.GetString(utf8data); + } + + public void CleanUpNativeData(IntPtr pNativeData) { + Marshal.FreeHGlobal(pNativeData); + } + + public void CleanUpManagedData(object managedObj) { + } + + public int GetNativeDataSize() { + return -1; + } + + public static ICustomMarshaler GetInstance(string cookie) { + if (static_instance == null) { + return static_instance = new UTF8Marshaler(); + } + return static_instance; + } + } %} +%typemap(imtype, inattributes="[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]", + outattributes="[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]") + char *, char *&, char[ANY], char[] "string" + %typemap(csout, excode=SWIGEXCODE) SWIGTYPE { /* %typemap(csout, excode=SWIGEXCODE) SWIGTYPE */ $&csclassname ret = new $&csclassname($imcall, true, null);$excode diff --git a/mapscript/java/CMakeLists.txt b/mapscript/java/CMakeLists.txt index 9987d42ec8..bafd894288 100644 --- a/mapscript/java/CMakeLists.txt +++ b/mapscript/java/CMakeLists.txt @@ -21,7 +21,7 @@ ADD_CUSTOM_COMMAND(TARGET javamapscript WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} POST_BUILD COMMAND ${Java_JAVAC_EXECUTABLE} edu/umn/gis/mapscript/*.java - COMMAND ${Java_JAR_EXECUTABLE} cf mapscript.jar edu + COMMAND ${Java_JAR_EXECUTABLE} cf mapscript.jar edu/umn/gis/mapscript/*.class COMMENT "Compiling java source files, creating mapscript.jar" ) diff --git a/mapscript/php/CMakeLists.txt b/mapscript/php/CMakeLists.txt index 89092cca0f..c4c952bf13 100644 --- a/mapscript/php/CMakeLists.txt +++ b/mapscript/php/CMakeLists.txt @@ -1,5 +1,9 @@ FIND_PACKAGE(PHP5 REQUIRED) -INCLUDE_DIRECTORIES(${PHP5_INCLUDES}) +INCLUDE_DIRECTORIES(${PHP5_INCLUDE_PATH}) + +if(WIN32) +add_definitions(/DZEND_WIN32 /DPHP_WIN32 /DPHP5 /DZTS /DZEND_DEBUG=0 -DWIN32 -D_WIN32 -D_USE_32BIT_TIME_T -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) +ENDIF(WIN32) IF(APPLE) if(XCODE) @@ -25,7 +29,11 @@ add_library(php_mapscript MODULE ) +if(WIN32) +target_link_libraries(php_mapscript ${MAPSERVER_LIBMAPSERVER} ${PHP5_LIBRARY}) +ELSE(WIN32) target_link_libraries(php_mapscript ${MAPSERVER_LIBMAPSERVER}) +ENDIF(WIN32) set_target_properties(php_mapscript PROPERTIES PREFIX "") install(TARGETS php_mapscript DESTINATION ${PHP5_EXTENSION_DIR}) diff --git a/mapscript/php/README.WIN32 b/mapscript/php/README.WIN32 index 374419383b..9da74518cd 100644 --- a/mapscript/php/README.WIN32 +++ b/mapscript/php/README.WIN32 @@ -1,95 +1,63 @@ PHP/MapScript Mapserver Module ============================== --------------------------------------------------------------------- -IMPORTANT - READ THIS FIRST: - - The Win32 build process is not very friendly for unexperienced users. - So it is strongly recommended that you use one of the precompiled - versions of php_mapscript.dll available on DM Solutions Group's web site: - http://www2.dmsolutions.ca/mapserver/dl/ - - If for some reason you still decide to compile Win32 binaries yourself, - then don't do it unless you really know what you're doing... and - hopefully the rest of this file contains some hints that may help - you. Good Luck! --------------------------------------------------------------------- - -This file contains informations specific to building the PHP/MapScript -extension on Windows using MSVC++ 6.0. +This README covers building PHP-Mapscript on Windows with Visual Studio 2012 Express for PHP-5.6 x86 Thread-Safe. -See also the file README for more general information about the -PHP/MapScript extension. +If you already built Mapserver with instructions from ../../README.WIN32, you are only a few steps away from PHP-Mapscript. +If not, first build Mapserver as descriped in ../../README.WIN32. - -------------------------- -Step 1: Build the PHP.LIB import library -======= - - *** PHP3 *** - Before you can build the 'php3_mapscript.dll' extension, you need the - PHP.LIB import library. To build PHP.LIB, you will have to download the - php_3.0.14.tar.gz source code, and follow the instructions in the - README.WIN32 file in there to build php.exe with MSVC++ 6.0. - - - Extract php_3.0.14.tar.gz to your HD - - Read the php_3.0.14\README.WIN32 file. - - Open php_3.0.14\win32\php3.dsw using MSVC++ 6.0 - - Start building php.exe, this will also create PHP.LIB - - *** PHP4.0.4 (and more recent versions) *** - The PHP 4.0.4 win32 binaries (php-4.0.4-Win32.zip) distributed on - http://www.php.net/ include the necessary php4ts.lib import library, - so it is not necessary to build the PHP4 source in this case: - - Extract php-4.0.4.tar.gz (this will create a php-4.0.4 source tree) - - Extract php-4.0.4-Win32.zip and configure PHP4 on your server as per - the instructions in the file install.txt included in the zip file. - - mkdir php-4.0.4\lib (i.e. 'mkdir lib' in the root of the source tree) - - Copy php4ts.lib (from php-4.0.4-Win32.zip) to php-4.0.4\lib - - Continue with the rest of the instructions below. +-------------------------------------------------------------------- +Step 1: Build PHP +-------------------------------------------------------------------- -Step 2: Build PHP3_MAPSCRIPT.DLL/PHP_MAPSCRIPT.DLL -======= +Build PHP-5.6 x86 Thread-Safe with Visual Studio 2012 Express as descriped here: https://wiki.php.net/internals/windows/stepbystepbuild +Extract the PHP-SDK to C:\dev\work\php-sdk to be able to use the commands, used here. -Review the mapscript\php3\makefile.vc and make any modifications required -for your configuration. Make sure PHP_SOURCE_DIR points to where you -installed the PHP source tree in step 1 above. +PHP sources and compiled binaries should be in C:\dev\work\php-sdk\phpdev\vc11\x86\php-5.6.28-src now. -Then to compile PHP3_MAPSCRIPT.DLL/PHP_MAPSCRIPT.DLL: - - Open a DOS prompt window - - Run the VCVARS32.BAT script to initialize the VC++ environment - variables. VCVARS32.BAT is automatically generated by the MSVC++ - install procedure and should be located in the BIN sub-directory of - your MSVC++ installation. - - Then start the build with: - nmake /f makefile.vc +-------------------------------------------------------------------- +Step 2: Build PHP-Mapscript +-------------------------------------------------------------------- -This will create the "PHP3_MAPSCRIPT.DLL" for PHP3, or "PHP_MAPSCRIPT.DLL" -for PHP4. +After step 5 of ../../README.WIN32 you have an open VS2012 x86 Native Tools Shell in build-Directory in your Mapserver sources (C:\dev\work\mapserver\build). +If not, open VS2012 x86 Native Tools Shell, add cmake to your PATH (see ../../README.WIN32) and "cd C:\dev\work\mapserver\build". +1. Tell CMake to build Mapscript by entering: + cmake .. -DWITH_PHP=1 -DPHP5_EXTENSION_DIR=C:\dev\builds\php-5.6.28-Win32-VC11-x86_mapscript\ext -DPHP5_INCLUDES=C:\dev\work\php-sdk\phpdev\vc11\x86\php-5.6.28-src +2. build: + nmake +-------------------------------------------------------------------- Step 3: Install PHP3_MAPSCRIPT.DLL/PHP_MAPSCRIPT.DLL -======= +-------------------------------------------------------------------- -PHP3_MAPSCRIPT.DLL is a regular PHP module, you should copy it to the same -directory as the other PHP3_*.DLL modules that came with PHP. +PHP_MAPSCRIPT.DLL is a regular PHP module, you should copy it to the same +directory as the other PHP_*.DLL modules that came with PHP. Then the module can be loaded in one of 2 ways: - - Adding a "extension=php3_mapscript.dll" line to the PHP3.INI file will + - Adding a "extension=php_mapscript.dll" line to the PHP3.INI file will load it automatically for every PHP page. - The other possibility is to load the module only when needed using the following PHP call: - dl("php3_mapscript.dll"); // for the PHP3 module - or dl("php_mapscript.dll"); // for the PHP4 module You can test that the module is properly loaded by executing the phpinfo() command in a PHP page... the "MapScript" extension should be included in the list of extensions in the phpinfo() report. +-------------------------------------------------------------------- +Maybe Step 4: Troubleshooting +-------------------------------------------------------------------- + +If you have any problems, getting PHP-MapScript running, add it to php.ini and try to start php from command line. It may tell you, what is missing. +PHP-MapScript has the same dependencies as Mapserver itself so you may need to add paths to the dependencies and libmap.dll/mapserver.dll to you systems PATH environment variable. +If this all does not help, use tools like SysInternals Process Monitor (https://technet.microsoft.com/de-de/sysinternals/processmonitor.aspx) or Dependency Walker (http://www.dependencywalker.com/) to find, what is missing. +Open php_mapscript.dll with Dependency Walker to see missing dependencies. + -------------------------- $Id$ diff --git a/mapscript/php/error.c b/mapscript/php/error.c index a13de647f3..2e96eea27b 100644 --- a/mapscript/php/error.c +++ b/mapscript/php/error.c @@ -31,6 +31,17 @@ #include "php_mapscript.h" +#if PHP_VERSION_ID >= 50625 +#undef ZVAL_STRING +#define ZVAL_STRING(z, s, duplicate) do { \ + const char *__s=(s); \ + zval *__z = (z); \ + Z_STRLEN_P(__z) = strlen(__s); \ + Z_STRVAL_P(__z) = (duplicate?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);\ + Z_TYPE_P(__z) = IS_STRING; \ +} while (0) +#endif + zend_class_entry *mapscript_ce_error; ZEND_BEGIN_ARG_INFO_EX(error___get_args, 0, 0, 1) diff --git a/mapscript/php/layer.c b/mapscript/php/layer.c index 0b4a743258..8567bc8e2b 100644 --- a/mapscript/php/layer.c +++ b/mapscript/php/layer.c @@ -271,32 +271,33 @@ PHP_METHOD(layerObj, __get) php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC); IF_GET_LONG("numclasses", php_layer->layer->numclasses) - else IF_GET_LONG("index", php_layer->layer->index) - else IF_GET_LONG("status", php_layer->layer->status) - else IF_GET_LONG("debug", php_layer->layer->debug) - else IF_GET_STRING("bandsitem", php_layer->layer->bandsitem) - else IF_GET_STRING("classitem", php_layer->layer->classitem) - else IF_GET_STRING("classgroup", php_layer->layer->classgroup) - else IF_GET_STRING("name", php_layer->layer->name) - else IF_GET_STRING("group", php_layer->layer->group) - else IF_GET_STRING("data", php_layer->layer->data) - else IF_GET_LONG("type", php_layer->layer->type) - else IF_GET_LONG("dump", php_layer->layer->dump) - else IF_GET_DOUBLE("tolerance", php_layer->layer->tolerance) - else IF_GET_LONG("toleranceunits", php_layer->layer->toleranceunits) - else IF_GET_LONG("sizeunits", php_layer->layer->sizeunits) - else IF_GET_DOUBLE("symbolscaledenom", php_layer->layer->symbolscaledenom) - else IF_GET_LONG("maxclasses", php_layer->layer->maxclasses) - else IF_GET_DOUBLE("minscaledenom", php_layer->layer->minscaledenom) - else IF_GET_DOUBLE("maxscaledenom", php_layer->layer->maxscaledenom) - else IF_GET_DOUBLE("labelminscaledenom", php_layer->layer->labelminscaledenom) - else IF_GET_DOUBLE("labelmaxscaledenom", php_layer->layer->labelmaxscaledenom) - else IF_GET_DOUBLE("maxgeowidth", php_layer->layer->maxgeowidth) - else IF_GET_DOUBLE("mingeowidth", php_layer->layer->mingeowidth) - else IF_GET_STRING("mask", php_layer->layer->mask) - else IF_GET_LONG("minfeaturesize", php_layer->layer->minfeaturesize) - else IF_GET_LONG("maxfeatures", php_layer->layer->maxfeatures) - else IF_GET_LONG("startindex", php_layer->layer->startindex) + else IF_GET_STRING("encoding", php_layer->layer->encoding) + else IF_GET_LONG("index", php_layer->layer->index) + else IF_GET_LONG("status", php_layer->layer->status) + else IF_GET_LONG("debug", php_layer->layer->debug) + else IF_GET_STRING("bandsitem", php_layer->layer->bandsitem) + else IF_GET_STRING("classitem", php_layer->layer->classitem) + else IF_GET_STRING("classgroup", php_layer->layer->classgroup) + else IF_GET_STRING("name", php_layer->layer->name) + else IF_GET_STRING("group", php_layer->layer->group) + else IF_GET_STRING("data", php_layer->layer->data) + else IF_GET_LONG("type", php_layer->layer->type) + else IF_GET_LONG("dump", php_layer->layer->dump) + else IF_GET_DOUBLE("tolerance", php_layer->layer->tolerance) + else IF_GET_LONG("toleranceunits", php_layer->layer->toleranceunits) + else IF_GET_LONG("sizeunits", php_layer->layer->sizeunits) + else IF_GET_DOUBLE("symbolscaledenom", php_layer->layer->symbolscaledenom) + else IF_GET_LONG("maxclasses", php_layer->layer->maxclasses) + else IF_GET_DOUBLE("minscaledenom", php_layer->layer->minscaledenom) + else IF_GET_DOUBLE("maxscaledenom", php_layer->layer->maxscaledenom) + else IF_GET_DOUBLE("labelminscaledenom", php_layer->layer->labelminscaledenom) + else IF_GET_DOUBLE("labelmaxscaledenom", php_layer->layer->labelmaxscaledenom) + else IF_GET_DOUBLE("maxgeowidth", php_layer->layer->maxgeowidth) + else IF_GET_DOUBLE("mingeowidth", php_layer->layer->mingeowidth) + else IF_GET_STRING("mask", php_layer->layer->mask) + else IF_GET_LONG("minfeaturesize", php_layer->layer->minfeaturesize) + else IF_GET_LONG("maxfeatures", php_layer->layer->maxfeatures) + else IF_GET_LONG("startindex", php_layer->layer->startindex) else IF_GET_LONG("transform", php_layer->layer->transform) else IF_GET_LONG("labelcache", php_layer->layer->labelcache) else IF_GET_LONG("postlabelcache", php_layer->layer->postlabelcache) @@ -354,29 +355,30 @@ PHP_METHOD(layerObj, __set) msSetLayerOpacity(php_layer->layer,Z_LVAL_P(value)); } else IF_SET_LONG("status", php_layer->layer->status, value) - else IF_SET_LONG("debug", php_layer->layer->debug, value) - else IF_SET_STRING("classitem", php_layer->layer->classitem, value) - else IF_SET_STRING("bandsitem", php_layer->layer->bandsitem, value) - else IF_SET_STRING("classgroup", php_layer->layer->classgroup, value) - else IF_SET_STRING("name", php_layer->layer->name, value) - else IF_SET_STRING("group", php_layer->layer->group, value) - else IF_SET_STRING("data", php_layer->layer->data, value) - else IF_SET_LONG("type", php_layer->layer->type, value) - else IF_SET_LONG("dump", php_layer->layer->dump, value) - else IF_SET_DOUBLE("tolerance", php_layer->layer->tolerance, value) - else IF_SET_LONG("toleranceunits", php_layer->layer->toleranceunits, value) - else IF_SET_LONG("sizeunits", php_layer->layer->sizeunits, value) - else IF_SET_DOUBLE("symbolscaledenom", php_layer->layer->symbolscaledenom, value) - else IF_SET_DOUBLE("minscaledenom", php_layer->layer->minscaledenom, value) - else IF_SET_DOUBLE("maxscaledenom", php_layer->layer->maxscaledenom, value) - else IF_SET_LONG("minfeaturesize", php_layer->layer->minfeaturesize, value) - else IF_SET_DOUBLE("labelminscaledenom", php_layer->layer->labelminscaledenom, value) - else IF_SET_DOUBLE("labelmaxscaledenom", php_layer->layer->labelmaxscaledenom, value) - else IF_SET_DOUBLE("maxgeowidth", php_layer->layer->maxgeowidth, value) - else IF_SET_DOUBLE("mingeowidth", php_layer->layer->mingeowidth, value) - else IF_SET_STRING("mask", php_layer->layer->mask, value) - else IF_SET_LONG("maxfeatures", php_layer->layer->maxfeatures, value) - else IF_SET_LONG("startindex", php_layer->layer->startindex, value) + else IF_SET_STRING("encoding", php_layer->layer->encoding, value) + else IF_SET_LONG("debug", php_layer->layer->debug, value) + else IF_SET_STRING("classitem", php_layer->layer->classitem, value) + else IF_SET_STRING("bandsitem", php_layer->layer->bandsitem, value) + else IF_SET_STRING("classgroup", php_layer->layer->classgroup, value) + else IF_SET_STRING("name", php_layer->layer->name, value) + else IF_SET_STRING("group", php_layer->layer->group, value) + else IF_SET_STRING("data", php_layer->layer->data, value) + else IF_SET_LONG("type", php_layer->layer->type, value) + else IF_SET_LONG("dump", php_layer->layer->dump, value) + else IF_SET_DOUBLE("tolerance", php_layer->layer->tolerance, value) + else IF_SET_LONG("toleranceunits", php_layer->layer->toleranceunits, value) + else IF_SET_LONG("sizeunits", php_layer->layer->sizeunits, value) + else IF_SET_DOUBLE("symbolscaledenom", php_layer->layer->symbolscaledenom, value) + else IF_SET_DOUBLE("minscaledenom", php_layer->layer->minscaledenom, value) + else IF_SET_DOUBLE("maxscaledenom", php_layer->layer->maxscaledenom, value) + else IF_SET_LONG("minfeaturesize", php_layer->layer->minfeaturesize, value) + else IF_SET_DOUBLE("labelminscaledenom", php_layer->layer->labelminscaledenom, value) + else IF_SET_DOUBLE("labelmaxscaledenom", php_layer->layer->labelmaxscaledenom, value) + else IF_SET_DOUBLE("maxgeowidth", php_layer->layer->maxgeowidth, value) + else IF_SET_DOUBLE("mingeowidth", php_layer->layer->mingeowidth, value) + else IF_SET_STRING("mask", php_layer->layer->mask, value) + else IF_SET_LONG("maxfeatures", php_layer->layer->maxfeatures, value) + else IF_SET_LONG("startindex", php_layer->layer->startindex, value) else IF_SET_LONG("transform", php_layer->layer->transform, value) else IF_SET_LONG("labelcache", php_layer->layer->labelcache, value) else IF_SET_LONG("postlabelcache", php_layer->layer->postlabelcache, value) diff --git a/mapscript/php/mapscript_error.c b/mapscript/php/mapscript_error.c index e2bef8ae57..4a0adce5e7 100644 --- a/mapscript/php/mapscript_error.c +++ b/mapscript/php/mapscript_error.c @@ -35,20 +35,19 @@ #include #include "../../maperror.h" -#define MAX_EXCEPTION_MSG 256 - zend_class_entry *mapscript_ce_mapscriptexception; zval* mapscript_throw_exception(char *format TSRMLS_DC, ...) { va_list args; - char message[MAX_EXCEPTION_MSG]; + char message[MESSAGELENGTH]; #ifdef ZTS va_start(args, TSRMLS_C); #else va_start(args, format); #endif - vsprintf(message, format, args); + //prevent buffer overflow + vsnprintf(message, MESSAGELENGTH, format, args); va_end(args); return zend_throw_exception(mapscript_ce_mapscriptexception, message, 0 TSRMLS_CC); } @@ -56,7 +55,7 @@ zval* mapscript_throw_exception(char *format TSRMLS_DC, ...) zval* mapscript_throw_mapserver_exception(char *format TSRMLS_DC, ...) { va_list args; - char message[MAX_EXCEPTION_MSG]; + char message[MESSAGELENGTH]; errorObj *ms_error; ms_error = msGetErrorObj(); @@ -73,21 +72,24 @@ zval* mapscript_throw_mapserver_exception(char *format TSRMLS_DC, ...) #else va_start(args, format); #endif - vsprintf(message, format, args); + //prevent buffer overflow + vsnprintf(message, MESSAGELENGTH, format, args); va_end(args); - return mapscript_throw_exception(message TSRMLS_CC); + //prevent format string attack + return mapscript_throw_exception("%s", message TSRMLS_CC); } void mapscript_report_php_error(int error_type, char *format TSRMLS_DC, ...) { va_list args; - char message[MAX_EXCEPTION_MSG]; + char message[MESSAGELENGTH]; #ifdef ZTS va_start(args, TSRMLS_C); #else va_start(args, format); #endif - vsprintf(message, format, args); + //prevent buffer overflow + vsnprintf(message, MESSAGELENGTH, format, args); va_end(args); php_error_docref(NULL TSRMLS_CC, error_type, "%s,", message); } diff --git a/mapscript/php/owsrequest.c b/mapscript/php/owsrequest.c index c28c953373..11d9996090 100644 --- a/mapscript/php/owsrequest.c +++ b/mapscript/php/owsrequest.c @@ -195,6 +195,8 @@ PHP_METHOD(OWSRequestObj, loadParams) #if PHP_VERSION_ID >= 50600 php_stream *s = php_stream_temp_new(); php_stream *input = php_stream_open_wrapper("php://input", "r", 0, NULL); + char *raw_post_data = NULL; + long raw_post_data_length = 0; /* php://input does not support stat */ php_stream_copy_to_stream_ex(input, s, -1, NULL); @@ -202,9 +204,6 @@ PHP_METHOD(OWSRequestObj, loadParams) php_stream_rewind(s); - char *raw_post_data = NULL; - long raw_post_data_length = 0; - raw_post_data_length = php_stream_copy_to_mem(s, raw_post_data, -1, 0); cgirequestObj_loadParams(php_owsrequest->cgirequest, owsrequest_getenv, diff --git a/mapscript/python/pymodule.i b/mapscript/python/pymodule.i index 08b7a6dd9c..76b68ee65f 100644 --- a/mapscript/python/pymodule.i +++ b/mapscript/python/pymodule.i @@ -102,6 +102,46 @@ CreateTupleFromDoubleArray( double *first, unsigned int size ) { $result = t_output_helper($result,r); } + +/* + * Typemap hashTableObj* -> dict + */ +%typemap(out) hashTableObj* +{ + /* %typemap(out) hashTableObj* */ + const char* key; + hashTableObj *hashTable = $1; + $result = PyDict_New(); + key = msFirstKeyFromHashTable(hashTable); + while( key ) + { + const char* val = msLookupHashTable(hashTable, key); + if( val ) + { +#if PY_VERSION_HEX >= 0x03000000 + PyObject *py_key = PyUnicode_FromString(key); + PyObject *py_val = PyUnicode_FromString(val); +#else + PyObject *py_key = PyString_FromString(key); + PyObject *py_val = PyString_FromString(val); +#endif + + PyDict_SetItem($result, py_key, py_val ); + Py_DECREF(py_key); + Py_DECREF(py_val); + } + key = msNextKeyFromHashTable(hashTable, key); + } +} + +%typemap(freearg) hashTableObj* +{ + /* %typemap(freearg) hashTableObj* */ + msFreeHashTable( $1 ); +} + + + /************************************************************************** * MapServer Errors and Python Exceptions ************************************************************************** diff --git a/mapscript/swiginc/class.i b/mapscript/swiginc/class.i index 425a3cd5a6..8eb0ff7dc2 100644 --- a/mapscript/swiginc/class.i +++ b/mapscript/swiginc/class.i @@ -176,7 +176,14 @@ return (char *) msNextKeyFromHashTable(&(self->metadata), lastkey); } - int drawLegendIcon(mapObj *map, layerObj *layer, int width, int height, imageObj *dstImage, int dstX, int dstY) { + int drawLegendIcon(mapObj *map, layerObj *layer, int width, int height, imageObj *dstImage, int dstX, int dstY) { + if(layer->sizeunits != MS_PIXELS) { + map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); + layer->scalefactor = (msInchesPerUnit(layer->sizeunits,0)/msInchesPerUnit(map->units,0)) / map->cellsize; + } + else + layer->scalefactor = map->resolution/map->defresolution; + return msDrawLegendIcon(map, layer, self, width, height, dstImage, dstX, dstY, MS_TRUE, NULL); } diff --git a/mapscript/swiginc/color.i b/mapscript/swiginc/color.i index 8b57dba053..2910673dae 100644 --- a/mapscript/swiginc/color.i +++ b/mapscript/swiginc/color.i @@ -42,7 +42,7 @@ /* Check colors */ if (red > 255 || green > 255 || blue > 255 || alpha>255 || - red<0 || green<0 || blue<0 || alpha<0 ) { + red<-1 || green<-1 || blue<-1 || alpha<0 ) { msSetError(MS_MISCERR, "Invalid color", "colorObj()"); return NULL; } diff --git a/mapscript/swiginc/msio.i b/mapscript/swiginc/msio.i index 45fe745fb5..3cee64de94 100644 --- a/mapscript/swiginc/msio.i +++ b/mapscript/swiginc/msio.i @@ -45,6 +45,11 @@ void msIO_stripStdoutBufferContentHeaders(void); const char *msIO_getStdoutBufferString(void); gdBuffer msIO_getStdoutBufferBytes(void); +#ifdef SWIGPYTHON +%newobject msIO_getAndStripStdoutBufferMimeHeaders; +hashTableObj* msIO_getAndStripStdoutBufferMimeHeaders(void); +#endif + %{ const char *msIO_getStdoutBufferString() { diff --git a/mapserv.c b/mapserv.c index 4ba25397c7..2e34335f8e 100644 --- a/mapserv.c +++ b/mapserv.c @@ -36,6 +36,8 @@ #include "mapio.h" #include "maptime.h" +#include "cpl_conv.h" + #ifndef WIN32 #include #endif @@ -52,7 +54,9 @@ void msCleanupOnSignal( int nInData ) /* from within the signal handler on Unix. So we force output through */ /* normal stdio functions. */ msIO_installHandlers( NULL, NULL, NULL ); +#ifndef NDEBUG msIO_fprintf( stderr, "In msCleanupOnSignal.\n" ); +#endif msCleanup(); exit(0); } @@ -154,6 +158,16 @@ int main(int argc, char *argv[]) if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&execstarttime, NULL); + /* push high-value ENV vars into the CPL global config - primarily for IIS/FastCGI */ + const char* const apszEnvVars[] = { + "CURL_CA_BUNDLE", "MS_MAPFILE", "MS_MAP_NO_PATH", "MS_MAP_PATTERN", "MS_MAP_ENV_PATTERN", + "MS_MAP_BAD_PATTERN", "MS_MAP_ENV_BAD_PATTERN", + NULL /* guard */ }; + for( int i = 0; apszEnvVars[i] != NULL; ++i ) { + const char* value = getenv(apszEnvVars[i]); + if(value) CPLSetConfigOption(apszEnvVars[i], value); + } + /* -------------------------------------------------------------------- */ /* Process arguments. In normal use as a cgi-bin there are no */ /* commandline switches, but we provide a few for test/debug */ diff --git a/mapserv.h b/mapserv.h index 845a544dac..27042a04e3 100644 --- a/mapserv.h +++ b/mapserv.h @@ -41,6 +41,7 @@ #include "maptile.h" #include "cgiutil.h" + /* ** Defines */ diff --git a/mapserver.h b/mapserver.h index 0526c00d20..808720b8e0 100644 --- a/mapserver.h +++ b/mapserver.h @@ -259,7 +259,7 @@ extern "C" { #define MS_URL_LENGTH 1024 #define MS_MAXPATHLEN 1024 -#define MS_MAXIMAGESIZE_DEFAULT 2048 +#define MS_MAXIMAGESIZE_DEFAULT 4096 #define MS_MAXPROJARGS 20 #define MS_MAXJOINS 20 @@ -474,7 +474,9 @@ extern "C" { #define MS_IS_VALID_ARRAY_INDEX(index, size) ((index<0 || index>=size)?MS_FALSE:MS_TRUE) #define MS_CONVERT_UNIT(src_unit, dst_unit, value) (value * msInchesPerUnit(src_unit,0) / msInchesPerUnit(dst_unit,0)) - + +#define MS_INIT_INVALID_RECT { -1e300, -1e300, 1e300, 1e300 } + #endif /* General enumerated types - needed by scripts */ @@ -1121,6 +1123,16 @@ extern "C" { labelLeaderObj *leader; }; + +#ifdef SWIG +#ifdef __cplusplus +extern "C" { +#endif +typedef struct labelObj labelObj; +#ifdef __cplusplus +} +#endif +#endif #ifndef SWIG /* lightweight structure containing information to render a labelObj */ @@ -2110,7 +2122,9 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char MS_DLL_EXPORT char *msWriteReferenceMapToString(referenceMapObj *ref); MS_DLL_EXPORT char *msWriteLegendToString(legendObj *legend); MS_DLL_EXPORT char *msWriteClusterToString(clusterObj *cluster); + MS_DLL_EXPORT int msIsValidRegex(const char* e); MS_DLL_EXPORT int msEvalRegex(const char *e, const char *s); + MS_DLL_EXPORT int msCaseEvalRegex(const char *e, const char *s); #ifdef USE_MSFREE MS_DLL_EXPORT void msFree(void *p); #else @@ -2308,7 +2322,7 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char MS_DLL_EXPORT int WARN_UNUSED msGetStringSize(mapObj *map, labelObj *label, int size, char *string, rectObj *r); MS_DLL_EXPORT int WARN_UNUSED msAddLabel(mapObj *map, imageObj *image, labelObj *label, int layerindex, int classindex, shapeObj *shape, pointObj *point, double featuresize, textSymbolObj *ts); - MS_DLL_EXPORT int WARN_UNUSED msAddLabelGroup(mapObj *map, imageObj *image, int layerindex, int classindex, shapeObj *shape, pointObj *point, double featuresize); + MS_DLL_EXPORT int WARN_UNUSED msAddLabelGroup(mapObj *map, imageObj *image, layerObj *layer, int classindex, shapeObj *shape, pointObj *point, double featuresize); MS_DLL_EXPORT void insertRenderedLabelMember(mapObj *map, labelCacheMemberObj *cachePtr); MS_DLL_EXPORT int msTestLabelCacheCollisions(mapObj *map, labelCacheMemberObj *cachePtr, label_bounds *lb, int current_priority, int current_label); MS_DLL_EXPORT int msTestLabelCacheLeaderCollision(mapObj *map, pointObj *lp1, pointObj *lp2); @@ -2410,6 +2424,7 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char MS_DLL_EXPORT int msClusterLayerOpen(layerObj *layer); /* in mapcluster.c */ MS_DLL_EXPORT int msLayerIsOpen(layerObj *layer); MS_DLL_EXPORT void msLayerClose(layerObj *layer); + MS_DLL_EXPORT void msLayerFreeExpressions(layerObj *layer); MS_DLL_EXPORT int msLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery); MS_DLL_EXPORT int msLayerGetItemIndex(layerObj *layer, char *item); MS_DLL_EXPORT int msLayerWhichItems(layerObj *layer, int get_all, const char *metadata); @@ -2490,6 +2505,8 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char MS_DLL_EXPORT int msUnionLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT void msPluginFreeVirtualTableFactory(void); + void msUVRASTERLayerUseMapExtentAndProjectionForNextWhichShapes(layerObj* layer, mapObj* map); + /* ==================================================================== */ /* Prototypes for functions in mapdraw.c */ /* ==================================================================== */ @@ -2586,6 +2603,7 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char MS_DLL_EXPORT int msGetClass(layerObj *layer, colorObj *color, int colormap_index); MS_DLL_EXPORT int msGetClass_FloatRGB(layerObj *layer, float fValue, int red, int green, int blue ); + int msGetClass_FloatRGB_WithFirstClassToTry(layerObj *layer, float fValue, int red, int green, int blue, int firstClassToTry ); /* in mapdrawgdal.c */ MS_DLL_EXPORT int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb, void *hDSVoid ); @@ -3130,6 +3148,8 @@ shapeObj *msOffsetCurve(shapeObj *p, double offset); shapeObj *msGEOSOffsetCurve(shapeObj *p, double offset); #endif +int msOGRIsSpatialite(layerObj* layer); + #endif /* SWIG */ #ifdef __cplusplus diff --git a/mapservutil.c b/mapservutil.c index 6b21676769..b5ac8e0783 100644 --- a/mapservutil.c +++ b/mapservutil.c @@ -33,6 +33,8 @@ #include "maptime.h" #include "mapows.h" +#include "cpl_conv.h" + /* ** Enumerated types, keep the query modes in sequence and at the end of the enumeration (mode enumeration is in maptemplate.h). */ @@ -199,38 +201,67 @@ mapObj *msCGILoadMap(mapservObj *mapserv) int i, j; mapObj *map = NULL; + const char *ms_map_bad_pattern_default = "[/\\]{2}|[/\\]?\\.+[/\\]|,"; + const char *ms_map_env_bad_pattern_default = "^(AUTH_.*|CERT_.*|CONTENT_(LENGTH|TYPE)|DOCUMENT_(ROOT|URI)|GATEWAY_INTERFACE|HTTP.*|QUERY_STRING|PATH_(INFO|TRANSLATED)|REMOTE_.*|REQUEST_(METHOD|URI)|SCRIPT_(FILENAME|NAME)|SERVER_.*)"; + + int ms_mapfile_tainted = MS_TRUE; + const char *ms_mapfile = CPLGetConfigOption("MS_MAPFILE", NULL); + + const char *ms_map_no_path = CPLGetConfigOption("MS_MAP_NO_PATH", NULL); + const char *ms_map_pattern = CPLGetConfigOption("MS_MAP_PATTERN", NULL); + const char *ms_map_env_pattern = CPLGetConfigOption("MS_MAP_ENV_PATTERN", NULL); + + const char *ms_map_bad_pattern = CPLGetConfigOption("MS_MAP_BAD_PATTERN", NULL); + if(ms_map_bad_pattern == NULL) ms_map_bad_pattern = ms_map_bad_pattern_default; + + const char *ms_map_env_bad_pattern = CPLGetConfigOption("MS_MAP_ENV_BAD_PATTERN", NULL); + if(ms_map_env_bad_pattern == NULL) ms_map_env_bad_pattern = ms_map_env_bad_pattern_default; + for(i=0; irequest->NumParams; i++) /* find the mapfile parameter first */ if(strcasecmp(mapserv->request->ParamNames[i], "map") == 0) break; if(i == mapserv->request->NumParams) { - char *ms_mapfile = getenv("MS_MAPFILE"); - if(ms_mapfile) { - map = msLoadMap(ms_mapfile,NULL); - } else { + if(ms_mapfile == NULL) { msSetError(MS_WEBERR, "CGI variable \"map\" is not set.", "msCGILoadMap()"); /* no default, outta here */ return NULL; } + ms_mapfile_tainted = MS_FALSE; } else { - if(getenv(mapserv->request->ParamValues[i])) /* an environment variable references the actual file to use */ - map = msLoadMap(getenv(mapserv->request->ParamValues[i]), NULL); - else { - /* by here we know the request isn't for something in an environment variable */ - if(getenv("MS_MAP_NO_PATH")) { - msSetError(MS_WEBERR, "Mapfile not found in environment variables and this server is not configured for full paths.", "msCGILoadMap()"); + if(getenv(mapserv->request->ParamValues[i])) { /* an environment variable references the actual file to use */ + /* validate env variable name */ + if(msIsValidRegex(ms_map_env_bad_pattern) == MS_FALSE || msCaseEvalRegex(ms_map_env_bad_pattern, mapserv->request->ParamValues[i]) == MS_TRUE) { + msSetError(MS_WEBERR, "CGI variable \"map\" fails to validate.", "msCGILoadMap()"); return NULL; } - - if(getenv("MS_MAP_PATTERN") && msEvalRegex(getenv("MS_MAP_PATTERN"), mapserv->request->ParamValues[i]) != MS_TRUE) { - msSetError(MS_WEBERR, "Parameter 'map' value fails to validate.", "msCGILoadMap()"); + if(ms_map_env_pattern != NULL && msEvalRegex(ms_map_env_pattern, mapserv->request->ParamValues[i]) != MS_TRUE) { + msSetError(MS_WEBERR, "CGI variable \"map\" fails to validate.", "msCGILoadMap()"); return NULL; } + ms_mapfile = getenv(mapserv->request->ParamValues[i]); + } else { + /* by now we know the request isn't for something in an environment variable */ + if(ms_map_no_path != NULL) { + msSetError(MS_WEBERR, "CGI variable \"map\" not found in environment and this server is not configured for full paths.", "msCGILoadMap()"); + return NULL; + } + ms_mapfile = mapserv->request->ParamValues[i]; + } + } - /* ok to try to load now */ - map = msLoadMap(mapserv->request->ParamValues[i], NULL); + /* validate ms_mapfile if tainted */ + if(ms_mapfile_tainted == MS_TRUE) { + if(msIsValidRegex(ms_map_bad_pattern) == MS_FALSE || msEvalRegex(ms_map_bad_pattern, ms_mapfile) == MS_TRUE) { + msSetError(MS_WEBERR, "CGI variable \"map\" fails to validate.", "msCGILoadMap()"); + return NULL; + } + if(ms_map_pattern != NULL && msEvalRegex(ms_map_pattern, ms_mapfile) != MS_TRUE) { + msSetError(MS_WEBERR, "CGI variable \"map\" fails to validate.", "msCGILoadMap()"); + return NULL; } } - + /* ok to try to load now */ + map = msLoadMap(ms_mapfile, NULL); if(!map) return NULL; if(!msLookupHashTable(&(map->web.validation), "immutable")) { diff --git a/mapshape.c b/mapshape.c index f1f71a5c29..7b720200f6 100644 --- a/mapshape.c +++ b/mapshape.c @@ -1934,6 +1934,10 @@ int msTiledSHPOpenFile(layerObj *layer) msTiledSHPLayerInfo *tSHP=NULL; + if (layer->layerinfo != NULL) { + return MS_SUCCESS; // Nothing to do... layer is already opened + } + if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; @@ -2206,6 +2210,7 @@ int msTiledSHPNextShape(layerObj *layer, shapeObj *shape) continue; } else if(status != MS_SUCCESS) { msShapefileClose(tSHP->shpfile); + tSHP->tileshpfile->lastshape = -1; return(MS_FAILURE); } @@ -2214,7 +2219,10 @@ int msTiledSHPNextShape(layerObj *layer, shapeObj *shape) break; } - if(status == MS_DONE) return(MS_DONE); /* no more tiles */ + if(status == MS_DONE) { + tSHP->tileshpfile->lastshape = -1; + return(MS_DONE); /* no more tiles */ + } else { msFreeShape(&tshape); continue; /* we've got shapes */ @@ -2248,6 +2256,7 @@ int msTiledSHPNextShape(layerObj *layer, shapeObj *shape) continue; } else if(status != MS_SUCCESS) { msShapefileClose(tSHP->shpfile); + tSHP->tileshpfile->lastshape = -1; return(MS_FAILURE); } @@ -2256,7 +2265,10 @@ int msTiledSHPNextShape(layerObj *layer, shapeObj *shape) } } /* end for loop */ - if(i == tSHP->tileshpfile->numshapes) return(MS_DONE); /* no more tiles */ + if(i == tSHP->tileshpfile->numshapes) { + tSHP->tileshpfile->lastshape = -1; + return(MS_DONE); /* no more tiles */ + } else continue; /* we've got shapes */ } } @@ -2304,6 +2316,8 @@ int msTiledSHPGetShape(layerObj *layer, shapeObj *shape, resultObj *record) return(MS_FAILURE); } + msTileIndexAbsoluteDir(tiFileAbsDir, layer); + if((tileindex < 0) || (tileindex >= tSHP->tileshpfile->numshapes)) return(MS_FAILURE); /* invalid tile id */ if(tileindex != tSHP->tileshpfile->lastshape) { /* correct tile is not currenly open so open the correct tile */ @@ -2332,6 +2346,7 @@ int msTiledSHPGetShape(layerObj *layer, shapeObj *shape, resultObj *record) msSHPReadShape(tSHP->shpfile->hSHP, shapeindex, shape); tSHP->shpfile->lastshape = shapeindex; + tSHP->tileshpfile->lastshape = tileindex; if(layer->numitems > 0 && layer->iteminfo) { shape->numvalues = layer->numitems; @@ -2624,8 +2639,8 @@ int msSHPLayerOpen(layerObj *layer) } OSRDestroySpatialReference(hSRS); } + fclose(fp); } - fclose(fp); if( bOK != MS_TRUE ) { diff --git a/mapstring.c b/mapstring.c index 122f4cd0f3..24d8c31410 100644 --- a/mapstring.c +++ b/mapstring.c @@ -728,8 +728,9 @@ char *msBuildPath(char *pszReturnPath, const char *abs_path, const char *path) abslen = strlen(abs_path); if((pathlen + abslen + 2) > MS_MAXPATHLEN) { - msSetError(MS_IOERR, "(%s%s): path is too long", "msBuildPath()", - abs_path, path); + msSetError(MS_IOERR, "Path is too long. Check server logs.", + "msBuildPath()"); + msDebug("msBuildPath(): (%s%s): path is too long.\n", abs_path, path); return NULL; } diff --git a/mapsymbol.c b/mapsymbol.c index e8029a1330..edb53bc3e7 100644 --- a/mapsymbol.c +++ b/mapsymbol.c @@ -300,12 +300,18 @@ void writeSymbol(symbolObj *s, FILE *stream) case(MS_SYMBOL_PIXMAP): msIO_fprintf(stream, " TYPE PIXMAP\n"); if(s->imagepath != NULL) msIO_fprintf(stream, " IMAGE \"%s\"\n", s->imagepath); + if(s->anchorpoint_y!=0.5 || s->anchorpoint_x!=0.5) { + msIO_fprintf(stream, " ANCHORPOINT %g %g\n", s->anchorpoint_x, s->anchorpoint_y); + } msIO_fprintf(stream, " TRANSPARENT %d\n", s->transparentcolor); break; case(MS_SYMBOL_TRUETYPE): msIO_fprintf(stream, " TYPE TRUETYPE\n"); if (s->character != NULL) msIO_fprintf(stream, " CHARACTER \"%s\"\n", s->character); if (s->font != NULL) msIO_fprintf(stream, " FONT \"%s\"\n", s->font); + if(s->anchorpoint_y!=0.5 || s->anchorpoint_x!=0.5) { + msIO_fprintf(stream, " ANCHORPOINT %g %g\n", s->anchorpoint_x, s->anchorpoint_y); + } break; default: if(s->type == MS_SYMBOL_ELLIPSE) diff --git a/maptemplate.c b/maptemplate.c index d091bdf489..70b64a7e69 100644 --- a/maptemplate.c +++ b/maptemplate.c @@ -3657,7 +3657,9 @@ static char *processLine(mapservObj *mapserv, char *instr, FILE *stream, int mod strlcat(repstr, " ", sizeof(repstr)); } msStringTrimBlanks(repstr); - outstr = msReplaceSubstring(outstr, "[layers]", repstr); + encodedstr = msEncodeHTMLEntities(repstr); + outstr = msReplaceSubstring(outstr, "[layers]", encodedstr); + free(encodedstr); encodedstr = msEncodeUrl(repstr); outstr = msReplaceSubstring(outstr, "[layers_esc]", encodedstr); diff --git a/maputfgrid.cpp b/maputfgrid.cpp index fb78332ae7..5ccb657bbf 100644 --- a/maputfgrid.cpp +++ b/maputfgrid.cpp @@ -284,10 +284,10 @@ band_type addToTable(UTFGridRenderer *r, shapeObj *p) /* Simple operation so we don't have unavailable char in the JSON */ utfvalue = encodeForRendering(utfvalue); - /* Datas are added to the table */ + /* Data added to the table */ r->data->table[r->data->counter].datavalues = msEvalTextExpressionJSonEscape(&r->utflayer->utfdata, p); - /* If UTFITEM is set in the mapfiles we add its value to the table */ + /* If UTFITEM is set in the mapfile we add its value to the table */ if(r->useutfitem) r->data->table[r->data->counter].itemvalue = msStrdup(p->values[r->utflayer->utfitemindex]); @@ -463,7 +463,7 @@ int utfgridCleanData(imageObj *img) } /* - * Print the renderer datas as a JSON. + * Print the renderer data as JSON. */ int utfgridSaveImage(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format) { @@ -483,28 +483,34 @@ int utfgridSaveImage(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *form msIO_fprintf(fp,"{\"grid\":["); - /* Print the buffer, also */ + /* Print the buffer */ for(row=0; rowwidth/renderer->utfresolution; col++) { - /* Get the datas from buffer. */ + /* Get the data from buffer. */ pixelid = renderer->buffer[(row*imgwidth)+col]; *stringptr = pixelid; stringptr++; } - /* Convertion to UTF-8 encoding */ + /* Conversion to UTF-8 encoding */ *stringptr = '\0'; char * utf8; - utf8 = msConvertWideStringToUTF8 (string, "UCS-4LE"); +#if defined(_WIN32) && !defined(__CYGWIN__) + const char* encoding = "UCS-2LE"; +#else + const char* encoding = "UCS-4LE"; +#endif + + utf8 = msConvertWideStringToUTF8(string, encoding); msIO_fprintf(fp,"%s", utf8); msFree(utf8); msFree(string); @@ -513,7 +519,7 @@ int utfgridSaveImage(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *form msIO_fprintf(fp,"],\"keys\":[\"\""); - /* Prints the key specified */ + /* Print the specified key */ for(i=0;idata->counter;i++) { msIO_fprintf(fp,","); @@ -530,7 +536,7 @@ int utfgridSaveImage(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *form msIO_fprintf(fp,"],\"data\":{"); - /* Print the datas */ + /* Print the data */ if(renderer->useutfdata) { for(i=0;idata->counter;i++) { if(i!=0) @@ -606,7 +612,7 @@ int utfgridEndLayer(imageObj *img, mapObj *map, layerObj *layer) } /* - * Do the table operations on the shapes. Allow multiple type of data to be rendered. + * Do the table operations on the shapes. Allow multiple types of data to be rendered. */ int utfgridStartShape(imageObj *img, shapeObj *shape) { @@ -633,7 +639,7 @@ int utfgridEndShape(imageObj *img, shapeObj *shape) } /* - * Function that render polygons into UTFGrid. + * Function that renders polygons into UTFGrid. */ int utfgridRenderPolygon(imageObj *img, shapeObj *polygonshape, colorObj *color) { @@ -652,8 +658,8 @@ int utfgridRenderPolygon(imageObj *img, shapeObj *polygonshape, colorObj *color) } /* - * Function that render lines into UTFGrid. Starts by looking if the line is a polygon - * outline. Then draw it if it's not. + * Function that renders lines into UTFGrid. Starts by looking if the line is a polygon + * outline, draw it if it's not. */ int utfgridRenderLine(imageObj *img, shapeObj *lineshape, strokeStyleObj *linestyle) { @@ -710,7 +716,7 @@ int utfgridRenderVectorSymbol(imageObj *img, double x, double y, symbolObj *symb } /* - * Function that render Pixmap type symbols into UTFGrid. + * Function that renders Pixmap type symbols into UTFGrid. */ int utfgridRenderPixmapSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style) { diff --git a/maputil.c b/maputil.c index 4c720d09a7..9a7da7b29e 100644 --- a/maputil.c +++ b/maputil.c @@ -1759,6 +1759,8 @@ shapeObj *msOffsetCurve(shapeObj *p, double offset) if that is the case.*/ if(ret) return ret; + /* clear error raised by geos in this case */ + msResetErrorList(); #endif /* ** For offset corner point calculation 1/sin() is used @@ -2258,6 +2260,14 @@ int msExtentsOverlap(mapObj *map, layerObj *layer) if( ! (layer->projection.numargs > 0) ) return msRectOverlap( &(map->extent), &(layer->extent) ); + /* In the case where map and layer projections are identical, and the */ + /* bounding boxes don't cross the dateline, do simple rectangle comparison */ + if( map->extent.minx < map->extent.maxx && + layer->extent.minx < layer->extent.maxx && + !msProjectionsDiffer(&(map->projection), &(layer->projection)) ) { + return msRectOverlap( &(map->extent), &(layer->extent) ); + } + /* We need to transform our rectangles for comparison, ** so we will work with copies and leave the originals intact. */ MS_COPYRECT(&map_extent, &(map->extent) ); diff --git a/mapuvraster.c b/mapuvraster.c index 52d92a52f2..ff6ae0c991 100644 --- a/mapuvraster.c +++ b/mapuvraster.c @@ -84,8 +84,17 @@ typedef struct { int next_shape; int x, y; /* used internally in msUVRasterLayerNextShape() */ + mapObj* mapToUseForWhichShapes; /* set if the map->extent and map->projection are valid in msUVRASTERLayerWhichShapes() */ + } uvRasterLayerInfo; +void msUVRASTERLayerUseMapExtentAndProjectionForNextWhichShapes(layerObj* layer, + mapObj* map) +{ + uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; + uvlinfo->mapToUseForWhichShapes = map; +} + static int msUVRASTERLayerInitItemInfo(layerObj *layer) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; @@ -345,8 +354,13 @@ int msUVRASTERLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) int width, height, u_src_off, v_src_off, i, x, y; char **alteredProcessing = NULL, *saved_layer_mask; char **savedProcessing = NULL; + int bHasLonWrap = MS_FALSE; + double dfLonWrap = 0.0; + rectObj oldLayerExtent; + char* oldLayerData = NULL; + projectionObj oldLayerProjection; + int ret; - if (layer->debug) msDebug("Entering msUVRASTERLayerWhichShapes().\n"); @@ -386,13 +400,6 @@ int msUVRASTERLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) width = (int)ceil(layer->map->width/spacing); height = (int)ceil(layer->map->height/spacing); - map_cellsize = MS_MAX(MS_CELLSIZE(rect.minx, rect.maxx,layer->map->width), - MS_CELLSIZE(rect.miny,rect.maxy,layer->map->height)); - map_tmp->cellsize = map_cellsize*spacing; - - if (layer->debug) - msDebug("msUVRASTERLayerWhichShapes(): width: %d, height: %d, cellsize: %g\n", - width, height, map_tmp->cellsize); /* Initialize our dummy map */ MS_INIT_COLOR(map_tmp->imagecolor, 255,255,255,255); @@ -413,13 +420,175 @@ int msUVRASTERLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) msCopyHashTable(&map_tmp->configoptions, &layer->map->configoptions); map_tmp->mappath = msStrdup(layer->map->mappath); map_tmp->shapepath = msStrdup(layer->map->shapepath); + map_tmp->gt.rotation_angle = 0.0; + + /* Custom msCopyProjection() that removes lon_wrap parameter */ + { +#ifdef USE_PROJ + int i; + + map_tmp->projection.numargs = 0; + map_tmp->projection.gt = layer->projection.gt; + map_tmp->projection.automatic = layer->projection.automatic; + + for (i = 0; i < layer->projection.numargs; i++) { + if( strncmp(layer->projection.args[i], "lon_wrap=", + strlen("lon_wrap=")) == 0 ) { + bHasLonWrap = MS_TRUE; + dfLonWrap = atof( layer->projection.args[i] + strlen("lon_wrap=") ); + } + else { + map_tmp->projection.args[map_tmp->projection.numargs ++] = + msStrdup(layer->projection.args[i]); + } + } + if (map_tmp->projection.numargs != 0) { + msProcessProjection(&(map_tmp->projection)); + } +#endif + map_tmp->projection.wellknownprojection = layer->projection.wellknownprojection; + } + + /* Very special case to improve quality for rasters referenced from lon=0 to 360 */ + /* We create a temporary VRT that swiches the 2 hemispheres, and then we */ + /* modify the georeferncing to be in the more standard [-180, 180] range */ + /* and we adjust the layer->data, extent and projection accordingly */ + if( layer->tileindex == NULL && + uvlinfo->mapToUseForWhichShapes && bHasLonWrap && dfLonWrap == 180.0 ) + { + rectObj layerExtent; + msLayerGetExtent(layer, &layerExtent); + if( layerExtent.minx == 0 && layerExtent.maxx == 360 ) + { + GDALDatasetH hDS = NULL; + char* decrypted_path; + + if( strncmp(layer->data, "data); + } + else + { + char szPath[MS_MAXPATHLEN]; + msTryBuildPath3(szPath, layer->map->mappath, + layer->map->shapepath, layer->data); + decrypted_path = msDecryptStringTokens( layer->map, szPath ); + } + + if( decrypted_path ) + { + GDALAllRegister(); + hDS = GDALOpen(decrypted_path, GA_ReadOnly ); + } + if( hDS != NULL ) + { + int iBand; + int nXSize = GDALGetRasterXSize( hDS ); + int nYSize = GDALGetRasterYSize( hDS ); + int nBands = GDALGetRasterCount( hDS ); + int nMaxLen = 100 + nBands * (800 + 2 * strlen(decrypted_path)); + int nOffset = 0; + char* pszInlineVRT = msSmallMalloc( nMaxLen ); + + snprintf(pszInlineVRT, nMaxLen, + "", + nXSize, nYSize); + nOffset = strlen(pszInlineVRT); + for( iBand = 1; iBand <= nBands; iBand++ ) + { + const char* pszDataType = "Byte"; + switch( GDALGetRasterDataType(GDALGetRasterBand(hDS, iBand)) ) + { + case GDT_Byte: pszDataType = "Byte"; break; + case GDT_Int16: pszDataType = "Int16"; break; + case GDT_UInt16: pszDataType = "UInt16"; break; + case GDT_Int32: pszDataType = "Int32"; break; + case GDT_UInt32: pszDataType = "UInt32"; break; + case GDT_Float32: pszDataType = "Float32"; break; + case GDT_Float64: pszDataType = "Float64"; break; + default: break; + } + + snprintf( pszInlineVRT + nOffset, nMaxLen - nOffset, + " " + " " + " " + " %d" + " " + " " + " " + " " + " " + " %d" + " " + " " + " " + " ", + pszDataType, iBand, + decrypted_path, iBand, + nXSize / 2, 0, nXSize - nXSize / 2, nYSize, + 0, 0, nXSize - nXSize / 2, nYSize, + decrypted_path, iBand, + 0, 0, nXSize / 2, nYSize, + nXSize - nXSize / 2, 0, nXSize / 2, nYSize ); + + nOffset += strlen(pszInlineVRT + nOffset); + } + snprintf(pszInlineVRT + nOffset, nMaxLen - nOffset, + ""); + + oldLayerExtent = layer->extent; + oldLayerData = layer->data; + oldLayerProjection = layer->projection; + layer->extent.minx = -180; + layer->extent.maxx = 180; + layer->data = pszInlineVRT; + layer->projection = map_tmp->projection; + + + /* map_tmp->projection is actually layer->projection without lon_wrap */ + rect = uvlinfo->mapToUseForWhichShapes->extent; + msProjectRect(&uvlinfo->mapToUseForWhichShapes->projection, + &map_tmp->projection, &rect); + bHasLonWrap = MS_FALSE; + + GDALClose(hDS); + } + msFree( decrypted_path ); + } + } + + + map_cellsize = MS_MAX(MS_CELLSIZE(rect.minx, rect.maxx,layer->map->width), + MS_CELLSIZE(rect.miny,rect.maxy,layer->map->height)); + map_tmp->cellsize = map_cellsize*spacing; map_tmp->extent.minx = rect.minx-(0.5*map_cellsize)+(0.5*map_tmp->cellsize); map_tmp->extent.miny = rect.miny-(0.5*map_cellsize)+(0.5*map_tmp->cellsize); map_tmp->extent.maxx = map_tmp->extent.minx+((width-1)*map_tmp->cellsize); map_tmp->extent.maxy = map_tmp->extent.miny+((height-1)*map_tmp->cellsize); - map_tmp->gt.rotation_angle = 0.0; - msCopyProjection(&map_tmp->projection, &layer->projection); + if( bHasLonWrap && dfLonWrap == 180.0) { + if( map_tmp->extent.minx >= 180 ) { + /* Request on the right half of the shifted raster (= western hemisphere) */ + map_tmp->extent.minx -= 360; + map_tmp->extent.maxx -= 360; + } + else if( map_tmp->extent.maxx >= 180.0 ) { + /* Request spanning on the 2 hemispheres => drawing whole planet */ + /* Take only into account vertical resolution, as horizontal one */ + /* will be unreliable (assuming square pixels...) */ + map_cellsize = MS_CELLSIZE(rect.miny,rect.maxy,layer->map->height); + map_tmp->cellsize = map_cellsize*spacing; + + width = 360.0 / map_tmp->cellsize; + map_tmp->extent.minx = -180.0+(0.5*map_tmp->cellsize); + map_tmp->extent.maxx = 180.0-(0.5*map_tmp->cellsize); + } + } + + if (layer->debug) + msDebug("msUVRASTERLayerWhichShapes(): width: %d, height: %d, cellsize: %g\n", + width, height, map_tmp->cellsize); if (layer->debug == 5) msDebug("msUVRASTERLayerWhichShapes(): extent: %g %g %g %g\n", @@ -458,17 +627,15 @@ int msUVRASTERLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) */ saved_layer_mask = layer->mask; layer->mask = NULL; - 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; + ret = msDrawRasterLayerLow(map_tmp, layer, image_tmp, NULL ); + + /* restore layer attributes if we went through the above on-the-fly VRT */ + if( oldLayerData ) + { + msFree(layer->data); + layer->data = oldLayerData; + layer->extent = oldLayerExtent; + layer->projection = oldLayerProjection; } /* restore layer mask */ @@ -480,6 +647,15 @@ int msUVRASTERLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) CSLDestroy(alteredProcessing); } + if( ret == MS_FAILURE) { + msSetError(MS_MISCERR, "Unable to draw raster data.", "msUVRASTERLayerWhichShapes()"); + + msFreeMap(map_tmp); + msFreeImage(image_tmp); + + return MS_FAILURE; + } + /* free old query arrays */ if (uvlinfo->u) { for (i=0; iwidth; ++i) { @@ -653,6 +829,8 @@ int msUVRASTERLayerGetExtent(layerObj *layer, rectObj *extent) msTryBuildPath3(szPath, map->mappath, map->shapepath, layer->data); decrypted_path = msDecryptStringTokens( map, szPath ); + GDALAllRegister(); + msAcquireLock( TLOCK_GDAL ); if( decrypted_path ) { hDS = GDALOpen(decrypted_path, GA_ReadOnly ); diff --git a/mapwcs11.c b/mapwcs11.c index 8dbe94829a..8bfd60fe9e 100644 --- a/mapwcs11.c +++ b/mapwcs11.c @@ -720,21 +720,29 @@ msWCSDescribeCoverage_CoverageDescription11( /* -------------------------------------------------------------------- */ { char format_buf[500]; + projectionObj proj; + double x0 = cm.geotransform[0]+cm.geotransform[1]/2+cm.geotransform[2]/2; + double y0 = cm.geotransform[3]+cm.geotransform[4]/2+cm.geotransform[5]/2; + double resx = cm.geotransform[1]; + double resy = cm.geotransform[5]; + + msInitProjection( &proj ); + if( msLoadProjectionString( &proj, cm.srs_urn ) == 0 ) { + msAxisNormalizePoints( &proj, 1, &x0, &y0 ); + msAxisNormalizePoints( &proj, 1, &resx, &resy ); + } + msFreeProjection( &proj ); psGridCRS = xmlNewChild( psSD, NULL, BAD_CAST "GridCRS", NULL ); - xmlNewChild( psGridCRS, NULL, BAD_CAST "GridBaseCRS", BAD_CAST cm.srs_urn ); xmlNewChild( psGridCRS, NULL, BAD_CAST "GridType", BAD_CAST "urn:ogc:def:method:WCS:1.1:2dSimpleGrid" ); - sprintf( format_buf, "%.15g %.15g", - cm.geotransform[0]+cm.geotransform[1]/2+cm.geotransform[2]/2, - cm.geotransform[3]+cm.geotransform[4]/2+cm.geotransform[5]/2); + sprintf( format_buf, "%.15g %.15g", x0, y0 ); xmlNewChild( psGridCRS, NULL, BAD_CAST "GridOrigin", BAD_CAST format_buf ); - sprintf( format_buf, "%.15g %.15g", - cm.geotransform[1], cm.geotransform[5] ); + sprintf( format_buf, "%.15g %.15g", resx, resy ); xmlNewChild( psGridCRS, NULL, BAD_CAST "GridOffsets", BAD_CAST format_buf ); xmlNewChild( psGridCRS, NULL, BAD_CAST "GridCS", diff --git a/mapwcs20.c b/mapwcs20.c index 266a07d1b5..e37079f1de 100644 --- a/mapwcs20.c +++ b/mapwcs20.c @@ -331,6 +331,7 @@ void msWCSFreeParamsObj20(wcs20ParamsObjPtr params) } msFree(params->axes); CSLDestroy(params->range_subset); + CSLDestroy(params->format_options); msFree(params); } @@ -740,6 +741,24 @@ xmlNodePtr msLibXml2GetFirstChildNs(xmlNodePtr parent, const char *name, xmlNsPt } return NULL; } + +/* + Utility function to get the first child of a node with a given node name + */ + +xmlNodePtr msLibXml2GetFirstChildElement(xmlNodePtr parent) { + xmlNodePtr node; + if (!parent) { + return NULL; + } + + XML_FOREACH_CHILD(parent, node) { + if (node->type == XML_ELEMENT_NODE) { + return node; + } + } + return NULL; +} #endif /* defined(USE_LIBXML2) */ /************************************************************************/ @@ -759,7 +778,6 @@ static int msWCSParseRequest20_XMLGetCapabilities( else if (EQUAL((char *)child->name, "AcceptVersions")) { xmlNodePtr versionNode = NULL; XML_FOREACH_CHILD(child, versionNode) { - /* for(child = firstChild->children; child != NULL; child = child->next) */ XML_LOOP_IGNORE_COMMENT_OR_TEXT(versionNode); XML_ASSERT_NODE_NAME(versionNode, "Version"); @@ -960,14 +978,17 @@ static int msWCSParseRequest20_XMLGetCoverage( if(NULL == (axis = msWCSFindAxis20(params, axisName))) { if(NULL == (axis = msWCSCreateAxisObj20())) { + xmlFree(axisName); return MS_FAILURE; } axis->name = msStrdup(axisName); msWCSInsertAxisObj20(params, axis); } + xmlFree(axisName); content = (char *)xmlNodeGetContent(child); if(msStringParseInteger(content, &(axis->size)) != MS_SUCCESS) { + xmlFree(content); msSetError(MS_WCSERR, "Value of element 'Size' could not " "be parsed to a valid integer.", "msWCSParseRequest20_XMLGetCoverage()"); @@ -988,11 +1009,13 @@ static int msWCSParseRequest20_XMLGetCoverage( if(NULL == (axis = msWCSFindAxis20(params, axisName))) { if(NULL == (axis = msWCSCreateAxisObj20())) { + xmlFree(axisName); return MS_FAILURE; } axis->name = msStrdup(axisName); msWCSInsertAxisObj20(params, axis); } + xmlFree(axisName); axis->resolutionUOM = (char *) xmlGetProp(child, BAD_CAST "uom"); @@ -1016,6 +1039,7 @@ static int msWCSParseRequest20_XMLGetCoverage( xmlNodePtr bandNode = NULL; XML_FOREACH_CHILD(child, bandNode) { char *content = NULL; + XML_LOOP_IGNORE_COMMENT_OR_TEXT(bandNode); XML_ASSERT_NODE_NAME(bandNode, "band"); content = (char *)xmlNodeGetContent(bandNode); @@ -1028,214 +1052,218 @@ static int msWCSParseRequest20_XMLGetCoverage( XML_FOREACH_CHILD(child, extensionNode) { XML_LOOP_IGNORE_COMMENT_OR_TEXT(extensionNode); - if (EQUAL((char *) extensionNode->name, "ScaleByFactor")) { - xmlNodePtr scaleFactorNode = extensionNode->children; - char *content; - if (!scaleFactorNode || !EQUAL((char *)scaleFactorNode->name, "scaleFactor")) { - msSetError(MS_WCSERR, "Missing 'scaleFactor' node.", - "msWCSParseRequest20_XMLGetCoverage()"); - return MS_FAILURE; - } - content = (char *)xmlNodeGetContent(scaleFactorNode); - if (msStringParseDouble(content, &(params->scale)) != MS_SUCCESS - || params->scale < 0.0) { - msSetError(MS_WCSERR, "Invalid scaleFactor '%s'.", - "msWCSParseRequest20_XMLGetCoverage()", content); - xmlFree(content); - return MS_FAILURE; - } - xmlFree(content); - } + if (EQUAL((char *) extensionNode->name, "Scaling")) { + xmlNodePtr scaleMethodNode = msLibXml2GetFirstChildElement(extensionNode); - else if (EQUAL((char *) extensionNode->name, "ScaleAxesByFactor")) { - xmlNodePtr scaleAxisNode, axisNode, scaleFactorNode; - char *axisName, *content; - wcs20AxisObjPtr axis; - - XML_FOREACH_CHILD(extensionNode, scaleAxisNode) { - XML_LOOP_IGNORE_COMMENT_OR_TEXT(scaleAxisNode); - - if (!EQUAL((char *)scaleAxisNode->name, "ScaleAxis")) { - msSetError(MS_WCSERR, "Invalid ScaleAxesByFactor.", + if (EQUAL((char *) scaleMethodNode->name, "ScaleByFactor")) { + xmlNodePtr scaleFactorNode = msLibXml2GetFirstChildElement(scaleMethodNode); + char *content; + if (!scaleFactorNode || !EQUAL((char *)scaleFactorNode->name, "scaleFactor")) { + msSetError(MS_WCSERR, "Missing 'scaleFactor' node.", "msWCSParseRequest20_XMLGetCoverage()"); return MS_FAILURE; } - - /* axis */ - if (NULL == (axisNode = msLibXml2GetFirstChild(scaleAxisNode, "axis"))) { - msSetError(MS_WCSERR, "Missing axis node", - "msWCSParseRequest20_XMLGetCoverage()"); + content = (char *)xmlNodeGetContent(scaleFactorNode); + if (msStringParseDouble(content, &(params->scale)) != MS_SUCCESS + || params->scale < 0.0) { + msSetError(MS_WCSERR, "Invalid scaleFactor '%s'.", + "msWCSParseRequest20_XMLGetCoverage()", content); + xmlFree(content); return MS_FAILURE; } - axisName = (char *)xmlNodeGetContent(axisNode); - if(NULL == (axis = msWCSFindAxis20(params, axisName))) { - if(NULL == (axis = msWCSCreateAxisObj20())) { - xmlFree(axisName); + xmlFree(content); + } + + else if (EQUAL((char *) scaleMethodNode->name, "ScaleAxesByFactor")) { + xmlNodePtr scaleAxisNode, axisNode, scaleFactorNode; + char *axisName, *content; + wcs20AxisObjPtr axis; + + XML_FOREACH_CHILD(scaleMethodNode, scaleAxisNode) { + XML_LOOP_IGNORE_COMMENT_OR_TEXT(scaleAxisNode); + + if (!EQUAL((char *)scaleAxisNode->name, "ScaleAxis")) { + msSetError(MS_WCSERR, "Invalid ScaleAxesByFactor.", + "msWCSParseRequest20_XMLGetCoverage()"); return MS_FAILURE; } - axis->name = msStrdup(axisName); - msWCSInsertAxisObj20(params, axis); - } - xmlFree(axisName); - if (axis->scale != MS_WCS20_UNBOUNDED) { - msSetError(MS_WCSERR, "scaleFactor was already set for axis '%s'.", - "msWCSParseRequest20_XMLGetCoverage()", axis->name); - return MS_FAILURE; - } + /* axis */ + if (NULL == (axisNode = msLibXml2GetFirstChild(scaleAxisNode, "axis"))) { + msSetError(MS_WCSERR, "Missing axis node", + "msWCSParseRequest20_XMLGetCoverage()"); + return MS_FAILURE; + } + axisName = (char *)xmlNodeGetContent(axisNode); + if(NULL == (axis = msWCSFindAxis20(params, axisName))) { + if(NULL == (axis = msWCSCreateAxisObj20())) { + xmlFree(axisName); + return MS_FAILURE; + } + axis->name = msStrdup(axisName); + msWCSInsertAxisObj20(params, axis); + } + xmlFree(axisName); - /* scaleFactor */ - if (NULL == (scaleFactorNode = msLibXml2GetFirstChild(scaleAxisNode, "scaleFactor"))) { - msSetError(MS_WCSERR, "Missing scaleFactor node", - "msWCSParseRequest20_XMLGetCoverage()"); - return MS_FAILURE; - } + if (axis->scale != MS_WCS20_UNBOUNDED) { + msSetError(MS_WCSERR, "scaleFactor was already set for axis '%s'.", + "msWCSParseRequest20_XMLGetCoverage()", axis->name); + return MS_FAILURE; + } - content = (char *)xmlNodeGetContent(scaleFactorNode); - if (msStringParseDouble(content, &(axis->scale)) != MS_SUCCESS - || axis->scale < 0.0) { - msSetError(MS_WCSERR, "Invalid scaleFactor '%s'.", - "msWCSParseRequest20_XMLGetCoverage()", content); + /* scaleFactor */ + if (NULL == (scaleFactorNode = msLibXml2GetFirstChild(scaleAxisNode, "scaleFactor"))) { + msSetError(MS_WCSERR, "Missing scaleFactor node", + "msWCSParseRequest20_XMLGetCoverage()"); + return MS_FAILURE; + } + + content = (char *)xmlNodeGetContent(scaleFactorNode); + if (msStringParseDouble(content, &(axis->scale)) != MS_SUCCESS + || axis->scale < 0.0) { + msSetError(MS_WCSERR, "Invalid scaleFactor '%s'.", + "msWCSParseRequest20_XMLGetCoverage()", content); + xmlFree(content); + return MS_FAILURE; + } xmlFree(content); - return MS_FAILURE; } - xmlFree(content); } - } - else if (EQUAL((char *) extensionNode->name, "ScaleToSize")) { - xmlNodePtr scaleAxisNode, axisNode, targetSizeNode; - char *axisName, *content; - wcs20AxisObjPtr axis; + else if (EQUAL((char *) scaleMethodNode->name, "ScaleToSize")) { + xmlNodePtr scaleAxisNode, axisNode, targetSizeNode; + char *axisName, *content; + wcs20AxisObjPtr axis; - XML_FOREACH_CHILD(extensionNode, scaleAxisNode) { - XML_LOOP_IGNORE_COMMENT_OR_TEXT(scaleAxisNode); + XML_FOREACH_CHILD(scaleMethodNode, scaleAxisNode) { + XML_LOOP_IGNORE_COMMENT_OR_TEXT(scaleAxisNode); - if (!EQUAL((char *)scaleAxisNode->name, "targetAxisSize")) { - msSetError(MS_WCSERR, "Invalid ScaleToSize.", - "msWCSParseRequest20_XMLGetCoverage()"); - return MS_FAILURE; - } + if (!EQUAL((char *)scaleAxisNode->name, "TargetAxisSize")) { + msSetError(MS_WCSERR, "Invalid ScaleToSize.", + "msWCSParseRequest20_XMLGetCoverage()"); + return MS_FAILURE; + } - /* axis */ - if (NULL == (axisNode = msLibXml2GetFirstChild(scaleAxisNode, "axis"))) { - msSetError(MS_WCSERR, "Missing axis node", - "msWCSParseRequest20_XMLGetCoverage()"); - return MS_FAILURE; - } - axisName = (char *)xmlNodeGetContent(axisNode); - if(NULL == (axis = msWCSFindAxis20(params, axisName))) { - if(NULL == (axis = msWCSCreateAxisObj20())) { - xmlFree(axisName); + /* axis */ + if (NULL == (axisNode = msLibXml2GetFirstChild(scaleAxisNode, "axis"))) { + msSetError(MS_WCSERR, "Missing axis node", + "msWCSParseRequest20_XMLGetCoverage()"); return MS_FAILURE; } - axis->name = msStrdup(axisName); - msWCSInsertAxisObj20(params, axis); - } - xmlFree(axisName); + axisName = (char *)xmlNodeGetContent(axisNode); + if(NULL == (axis = msWCSFindAxis20(params, axisName))) { + if(NULL == (axis = msWCSCreateAxisObj20())) { + xmlFree(axisName); + return MS_FAILURE; + } + axis->name = msStrdup(axisName); + msWCSInsertAxisObj20(params, axis); + } + xmlFree(axisName); - if (axis->size != 0) { - msSetError(MS_WCSERR, "targetSize was already set for axis '%s'.", - "msWCSParseRequest20_XMLGetCoverage()", axis->name); - return MS_FAILURE; - } + if (axis->size != 0) { + msSetError(MS_WCSERR, "targetSize was already set for axis '%s'.", + "msWCSParseRequest20_XMLGetCoverage()", axis->name); + return MS_FAILURE; + } - /* targetSize */ - if (NULL == (targetSizeNode = msLibXml2GetFirstChild(scaleAxisNode, "targetSize"))) { - msSetError(MS_WCSERR, "Missing targetSize node", - "msWCSParseRequest20_XMLGetCoverage()"); - return MS_FAILURE; - } + /* targetSize */ + if (NULL == (targetSizeNode = msLibXml2GetFirstChild(scaleAxisNode, "targetSize"))) { + msSetError(MS_WCSERR, "Missing targetSize node", + "msWCSParseRequest20_XMLGetCoverage()"); + return MS_FAILURE; + } - content = (char *)xmlNodeGetContent(targetSizeNode); - if (msStringParseInteger(content, &(axis->size)) != MS_SUCCESS - || axis->size <= 0) { - msSetError(MS_WCSERR, "Invalid targetSize '%s'.", - "msWCSParseRequest20_XMLGetCoverage()", content); + content = (char *)xmlNodeGetContent(targetSizeNode); + if (msStringParseInteger(content, &(axis->size)) != MS_SUCCESS + || axis->size <= 0) { + msSetError(MS_WCSERR, "Invalid targetSize '%s'.", + "msWCSParseRequest20_XMLGetCoverage()", content); + xmlFree(content); + return MS_FAILURE; + } xmlFree(content); - return MS_FAILURE; } - xmlFree(content); } - } - else if (EQUAL((char *) extensionNode->name, "ScaleToExtent")) { - xmlNodePtr scaleAxisNode, axisNode, lowNode, highNode; - char *axisName, *content; - wcs20AxisObjPtr axis; - int low, high; + else if (EQUAL((char *) scaleMethodNode->name, "ScaleToExtent")) { + xmlNodePtr scaleAxisNode, axisNode, lowNode, highNode; + char *axisName, *content; + wcs20AxisObjPtr axis; + int low, high; - XML_FOREACH_CHILD(extensionNode, scaleAxisNode) { - XML_LOOP_IGNORE_COMMENT_OR_TEXT(scaleAxisNode); + XML_FOREACH_CHILD(scaleMethodNode, scaleAxisNode) { + XML_LOOP_IGNORE_COMMENT_OR_TEXT(scaleAxisNode); - if (!EQUAL((char *)scaleAxisNode->name, "TargetAxisExtent")) { - msSetError(MS_WCSERR, "Invalid ScaleToExtent.", - "msWCSParseRequest20_XMLGetCoverage()"); - return MS_FAILURE; - } + if (!EQUAL((char *)scaleAxisNode->name, "TargetAxisExtent")) { + msSetError(MS_WCSERR, "Invalid ScaleToExtent.", + "msWCSParseRequest20_XMLGetCoverage()"); + return MS_FAILURE; + } - /* axis */ - if (NULL == (axisNode = msLibXml2GetFirstChild(scaleAxisNode, "axis"))) { - msSetError(MS_WCSERR, "Missing axis node", - "msWCSParseRequest20_XMLGetCoverage()"); - return MS_FAILURE; - } - axisName = (char *)xmlNodeGetContent(axisNode); - if(NULL == (axis = msWCSFindAxis20(params, axisName))) { - if(NULL == (axis = msWCSCreateAxisObj20())) { - xmlFree(axisName); + /* axis */ + if (NULL == (axisNode = msLibXml2GetFirstChild(scaleAxisNode, "axis"))) { + msSetError(MS_WCSERR, "Missing axis node", + "msWCSParseRequest20_XMLGetCoverage()"); return MS_FAILURE; } - axis->name = msStrdup(axisName); - msWCSInsertAxisObj20(params, axis); - } - xmlFree(axisName); + axisName = (char *)xmlNodeGetContent(axisNode); + if(NULL == (axis = msWCSFindAxis20(params, axisName))) { + if(NULL == (axis = msWCSCreateAxisObj20())) { + xmlFree(axisName); + return MS_FAILURE; + } + axis->name = msStrdup(axisName); + msWCSInsertAxisObj20(params, axis); + } + xmlFree(axisName); - if (axis->size != 0) { - msSetError(MS_WCSERR, "targetSize was already set for axis '%s'.", - "msWCSParseRequest20_XMLGetCoverage()", axis->name); - return MS_FAILURE; - } + if (axis->size != 0) { + msSetError(MS_WCSERR, "targetSize was already set for axis '%s'.", + "msWCSParseRequest20_XMLGetCoverage()", axis->name); + return MS_FAILURE; + } - /* targetSize */ - if (NULL == (lowNode = msLibXml2GetFirstChild(scaleAxisNode, "low"))) { - msSetError(MS_WCSERR, "Missing low node", - "msWCSParseRequest20_XMLGetCoverage()"); - return MS_FAILURE; - } + /* targetSize */ + if (NULL == (lowNode = msLibXml2GetFirstChild(scaleAxisNode, "low"))) { + msSetError(MS_WCSERR, "Missing low node", + "msWCSParseRequest20_XMLGetCoverage()"); + return MS_FAILURE; + } - if (NULL == (highNode = msLibXml2GetFirstChild(scaleAxisNode, "high"))) { - msSetError(MS_WCSERR, "Missing high node", - "msWCSParseRequest20_XMLGetCoverage()"); - return MS_FAILURE; - } + if (NULL == (highNode = msLibXml2GetFirstChild(scaleAxisNode, "high"))) { + msSetError(MS_WCSERR, "Missing high node", + "msWCSParseRequest20_XMLGetCoverage()"); + return MS_FAILURE; + } - content = (char *)xmlNodeGetContent(lowNode); - if (msStringParseInteger(content, &low) != MS_SUCCESS) { - msSetError(MS_WCSERR, "Invalid low value '%s'.", - "msWCSParseRequest20_XMLGetCoverage()", content); + content = (char *)xmlNodeGetContent(lowNode); + if (msStringParseInteger(content, &low) != MS_SUCCESS) { + msSetError(MS_WCSERR, "Invalid low value '%s'.", + "msWCSParseRequest20_XMLGetCoverage()", content); + xmlFree(content); + return MS_FAILURE; + } xmlFree(content); - return MS_FAILURE; - } - xmlFree(content); - content = (char *)xmlNodeGetContent(highNode); - if (msStringParseInteger(content, &high) != MS_SUCCESS) { - msSetError(MS_WCSERR, "Invalid high value '%s'.", - "msWCSParseRequest20_XMLGetCoverage()", content); + content = (char *)xmlNodeGetContent(highNode); + if (msStringParseInteger(content, &high) != MS_SUCCESS) { + msSetError(MS_WCSERR, "Invalid high value '%s'.", + "msWCSParseRequest20_XMLGetCoverage()", content); + xmlFree(content); + return MS_FAILURE; + } xmlFree(content); - return MS_FAILURE; - } - xmlFree(content); - if (high <= low) { - msSetError(MS_WCSERR, "Invalid extent, high is lower than low.", - "msWCSParseRequest20_XMLGetCoverage()"); - return MS_FAILURE; - } + if (high <= low) { + msSetError(MS_WCSERR, "Invalid extent, high is lower than low.", + "msWCSParseRequest20_XMLGetCoverage()"); + return MS_FAILURE; + } - axis->size = high - low; + axis->size = high - low; + } } } @@ -1244,39 +1272,39 @@ static int msWCSParseRequest20_XMLGetCoverage( xmlNodePtr rangeItemNode = NULL; XML_FOREACH_CHILD(extensionNode, rangeItemNode) { - + xmlNodePtr rangeItemNodeChild = msLibXml2GetFirstChildElement(rangeItemNode); XML_LOOP_IGNORE_COMMENT_OR_TEXT(rangeItemNode); XML_ASSERT_NODE_NAME(rangeItemNode, "RangeItem"); - if (!rangeItemNode->children) { + if (!rangeItemNodeChild) { msSetError(MS_WCSERR, "Missing RangeComponent or RangeInterval.", "msWCSParseRequest20_XMLGetCoverage()"); return MS_FAILURE; } - else if (EQUAL((char *) rangeItemNode->children->name, "RangeComponent")) { - char *content = (char *)xmlNodeGetContent(rangeItemNode->children); + else if (EQUAL((char *) rangeItemNodeChild->name, "RangeComponent")) { + char *content = (char *)xmlNodeGetContent(rangeItemNodeChild); params->range_subset = CSLAddString(params->range_subset, content); xmlFree(content); } - else if (EQUAL((char *) rangeItemNode->children->name, "RangeInterval")) { - xmlNodePtr intervalNode = rangeItemNode->children; + else if (EQUAL((char *) rangeItemNodeChild->name, "RangeInterval")) { + xmlNodePtr intervalNode = rangeItemNodeChild; + xmlNodePtr startComponentNode = msLibXml2GetFirstChild(intervalNode, "startComponent"); + xmlNodePtr endComponentNode = msLibXml2GetFirstChild(intervalNode, "endComponent"); char *start; char *stop; char *value; int length; - if (!intervalNode->children || !intervalNode->children->next - || !EQUAL((char *) intervalNode->children->name, "startComponent") - || !EQUAL((char *) intervalNode->children->next->name, "endComponent")) { + if (!startComponentNode || !endComponentNode) { msSetError(MS_WCSERR, "Wrong RangeInterval.", "msWCSParseRequest20_XMLGetCoverage()"); return MS_FAILURE; } - start = (char *)xmlNodeGetContent(intervalNode->children); - stop = (char *)xmlNodeGetContent(intervalNode->children->next); + start = (char *)xmlNodeGetContent(startComponentNode); + stop = (char *)xmlNodeGetContent(endComponentNode); length = strlen(start) + strlen(stop) + 2; value = msSmallCalloc(length, sizeof(char)); @@ -1303,10 +1331,9 @@ static int msWCSParseRequest20_XMLGetCoverage( } else if (EQUAL((char *) extensionNode->name, "Interpolation")) { - xmlNodePtr globalInterpolation; + xmlNodePtr globalInterpolation = msLibXml2GetFirstChild(extensionNode, "globalInterpolation"); char *content; - if ((globalInterpolation = extensionNode->children) == NULL - || !EQUAL((char *)globalInterpolation->name, "globalInterpolation")) { + if (globalInterpolation == NULL) { msSetError(MS_WCSERR, "Missing 'globalInterpolation' node.", "msWCSParseRequest20_XMLGetCoverage()"); return MS_FAILURE; @@ -2003,12 +2030,18 @@ static void msWCSCommon20_CreateDomainSet(layerObj* layer, wcs20coverageMetadata { xmlNodePtr psDomainSet, psGrid, psLimits, psGridEnvelope, psOrigin, psOffsetX, psOffsetY; - char low[100], high[100], id[100], point[100], resx[100], resy[100], axisLabels[100]; + char low[100], high[100], id[100], point[100]; + char offsetVector1[100], offsetVector2[100], axisLabels[100]; psDomainSet = xmlNewChild( psRoot, psGmlNs, BAD_CAST "domainSet", NULL); { psGrid = xmlNewChild(psDomainSet, psGmlNs, BAD_CAST "RectifiedGrid", NULL); { + double x0 = cm->geotransform[0]+cm->geotransform[1]/2+cm->geotransform[2]/2; + double y0 = cm->geotransform[3]+cm->geotransform[4]/2+cm->geotransform[5]/2; + double resx = cm->geotransform[1]; + double resy = cm->geotransform[5]; + xmlNewProp(psGrid, BAD_CAST "dimension", BAD_CAST "2"); snprintf(id, sizeof(id), "grid_%s", layer->name); xmlNewNsProp(psGrid, psGmlNs, BAD_CAST "id", BAD_CAST id); @@ -2026,17 +2059,9 @@ static void msWCSCommon20_CreateDomainSet(layerObj* layer, wcs20coverageMetadata } if(projection->proj != NULL && pj_is_latlong(projection->proj)) { - if (swapAxes == MS_FALSE) { - strlcpy(axisLabels, "long lat", sizeof(axisLabels)); - } else { - strlcpy(axisLabels, "lat long", sizeof(axisLabels)); - } + strlcpy(axisLabels, "long lat", sizeof(axisLabels)); } else { - if (swapAxes == MS_FALSE) { - strlcpy(axisLabels, "x y", sizeof(axisLabels)); - } else { - strlcpy(axisLabels, "y x", sizeof(axisLabels)); - } + strlcpy(axisLabels, "x y", sizeof(axisLabels)); } xmlNewChild(psGrid, psGmlNs, BAD_CAST "axisLabels", BAD_CAST axisLabels); @@ -2044,9 +2069,9 @@ static void msWCSCommon20_CreateDomainSet(layerObj* layer, wcs20coverageMetadata psOrigin = xmlNewChild(psGrid, psGmlNs, BAD_CAST "origin", NULL); { if (swapAxes == MS_FALSE) { - snprintf(point, sizeof(point), "%f %f", cm->extent.minx, cm->extent.maxy); + snprintf(point, sizeof(point), "%f %f", x0, y0); } else { - snprintf(point, sizeof(point), "%f %f", cm->extent.maxy, cm->extent.minx); + snprintf(point, sizeof(point), "%f %f", y0, x0); } psOrigin = xmlNewChild(psOrigin, psGmlNs, BAD_CAST "Point", NULL); snprintf(id, sizeof(id), "grid_origin_%s", layer->name); @@ -2057,14 +2082,14 @@ static void msWCSCommon20_CreateDomainSet(layerObj* layer, wcs20coverageMetadata } if (swapAxes == MS_FALSE) { - snprintf(resx, sizeof(resx), "%f 0", cm->xresolution); - snprintf(resy, sizeof(resy), "0 %f", -fabs(cm->yresolution)); + snprintf(offsetVector1, sizeof(offsetVector1), "%f 0", resx); + snprintf(offsetVector2, sizeof(offsetVector2), "0 %f", resy); } else { - snprintf(resx, sizeof(resx), "0 %f", cm->xresolution); - snprintf(resy, sizeof(resy), "%f 0", -fabs(cm->yresolution)); + snprintf(offsetVector1, sizeof(offsetVector1), "0 %f", resx); + snprintf(offsetVector2, sizeof(offsetVector2), "%f 0", resy); } - psOffsetX = xmlNewChild(psGrid, psGmlNs, BAD_CAST "offsetVector", BAD_CAST resx); - psOffsetY = xmlNewChild(psGrid, psGmlNs, BAD_CAST "offsetVector", BAD_CAST resy); + psOffsetX = xmlNewChild(psGrid, psGmlNs, BAD_CAST "offsetVector", BAD_CAST offsetVector1); + psOffsetY = xmlNewChild(psGrid, psGmlNs, BAD_CAST "offsetVector", BAD_CAST offsetVector2); xmlNewProp(psOffsetX, BAD_CAST "srsName", BAD_CAST cm->srs_uri); xmlNewProp(psOffsetY, BAD_CAST "srsName", BAD_CAST cm->srs_uri); @@ -2677,7 +2702,26 @@ static int msWCSGetCoverageMetadata20(layerObj *layer, wcs20coverageMetadataObj } else if( (value = msOWSLookupMetadata(&(layer->metadata), "CO", wcs11_band_names_key)) != NULL ) { keys = wcs11_keys; interval_key = wcs11_interval_key; - band_names = msStringSplit(value, ' ', &num_band_names); + /* "bands" has a special processing in WCS 1.0. See */ + /* msWCSSetDefaultBandsRangeSetInfo */ + if( EQUAL(value, "bands") ) + { + num_band_names = cm->numbands; + band_names = (char**) msSmallMalloc( sizeof(char*) * num_band_names ); + for( i = 0; i < num_band_names; i++ ) + { + char szName[30]; + snprintf(szName, sizeof(szName), "Band%d", i+1); + band_names[i] = msStrdup(szName); + } + } + else + { + /* WARNING: in WCS 1.x,, "rangeset_axes" has never been intended */ + /* to contain the list of band names... This code should probably */ + /* be removed */ + band_names = msStringSplit(value, ' ', &num_band_names); + } } /* return with error when number of bands does not match */ @@ -3338,7 +3382,7 @@ int msWCSGetCapabilities20(mapObj *map, cgiRequestObj *req, /* Report the supported CRSs */ { - char *crs_list; + char *crs_list = NULL; xmlNodePtr crsMetadataNode = xmlNewChild(psExtensionNode, psCrsNs, BAD_CAST "CrsMetadata", NULL); @@ -3347,6 +3391,7 @@ int msWCSGetCapabilities20(mapObj *map, cgiRequestObj *req, "CO", MS_FALSE)) != NULL ) { msLibXml2GenerateList(crsMetadataNode, psCrsNs, "crsSupported", crs_list, ' '); + msFree(crs_list); } else { /* could not determine list of CRSs */ } @@ -3743,21 +3788,47 @@ static int msWCSGetCoverage20_GetBands(mapObj *map, layerObj *layer, return MS_SUCCESS; } - count = CSLCount(params->range_subset); maxlen = cm->numbands * 4 * sizeof(char); *bandlist = msSmallCalloc(sizeof(char), maxlen); - if (NULL == (tmp = msOWSGetEncodeMetadata(&layer->metadata, - "CO", "rangeset_axes", NULL))) { - tmp = msOWSGetEncodeMetadata(&layer->metadata, - "CO", "band_names", NULL); + /* Use WCS 2.0 metadata items in priority */ + tmp = msOWSGetEncodeMetadata(&layer->metadata, + "CO", "band_names", NULL); + + if( NULL == tmp ) { + /* Otherwise default to WCS 1.x*/ + tmp = msOWSGetEncodeMetadata(&layer->metadata, + "CO", "rangeset_axes", NULL); + /* "bands" has a special processing in WCS 1.0. See */ + /* msWCSSetDefaultBandsRangeSetInfo */ + if( tmp != NULL && EQUAL(tmp, "bands") ) + { + int num_band_names = cm->numbands; + band_ids = (char**) msSmallCalloc( sizeof(char*), (num_band_names + 1) ); + for( i = 0; i < num_band_names; i++ ) + { + char szName[30]; + snprintf(szName, sizeof(szName), "Band%d", i+1); + band_ids[i] = msStrdup(szName); + } + } } - if(NULL != tmp) { + if(NULL != tmp && band_ids == NULL) { band_ids = CSLTokenizeString2(tmp, " ", 0); msFree(tmp); } + /* If we still don't have band names, use the band names from the coverage metadata */ + if (band_ids == NULL) { + band_ids = (char**) CPLCalloc(sizeof(char*), (cm->numbands + 1)); + for (i = 0; i < cm->numbands; ++i) { + band_ids[i] = CPLStrdup(cm->bands[i].name); + } + } + + /* Iterate over all supplied range */ + count = CSLCount(params->range_subset); for(i = 0; i < count; ++i) { /* RangeInterval case: defined as ":" */ if ((interval_stop = strchr(params->range_subset[i], ':')) != NULL) { @@ -4067,6 +4138,10 @@ int msWCSGetCoverage20(mapObj *map, cgiRequestObj *request, double x_1, x_2, y_1, y_2; char *coverageName, *bandlist=NULL, numbands[8]; + + int widthFromComputationInImageCRS = 0; + int heightFromComputationInImageCRS = 0; + /* number of coverage ids should be 1 */ if (params->ids == NULL || params->ids[0] == NULL) { msSetError(MS_WCSERR, "Required parameter CoverageID was not supplied.", @@ -4126,6 +4201,7 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p msInitProjection(&imageProj); if (msLoadProjectionString(&imageProj, cm.srs) == -1) { + msFreeProjection(&imageProj); msWCSClearCoverageMetadata20(&cm); msSetError(MS_WCSERR, "Error loading CRS %s.", @@ -4138,11 +4214,15 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p for(i = 0; i < params->numaxes; ++i) { if(params->axes[i]->subset != NULL) { if(params->axes[i]->subset->timeOrScalar == MS_WCS20_TIME_VALUE) { + msFreeProjection(&imageProj); + msWCSClearCoverageMetadata20(&cm); msSetError(MS_WCSERR, "Time values for subsets are not supported. ", "msWCSGetCoverage20()"); return msWCSException(map, "InvalidSubsetting", "subset", params->version); } if(params->axes[i]->subset->operation == MS_WCS20_SLICE) { + msFreeProjection(&imageProj); + msWCSClearCoverageMetadata20(&cm); msSetError(MS_WCSERR, "Subset operation 'slice' is not supported.", "msWCSGetCoverage20()"); return msWCSException(map, "InvalidSubsetting", "subset", params->version); @@ -4154,11 +4234,13 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p wcs20AxisObjPtr *axes; axes = msSmallMalloc(sizeof(wcs20AxisObjPtr) * 2); if(msWCSValidateAndFindAxes20(params, axes) == MS_FAILURE) { + msFreeProjection(&imageProj); msWCSClearCoverageMetadata20(&cm); msFree(axes); return msWCSException(map, "InvalidAxisLabel", "subset", params->version); } if(msWCSGetCoverage20_FinalizeParamsObj(params, axes) == MS_FAILURE) { + msFreeProjection(&imageProj); msWCSClearCoverageMetadata20(&cm); msFree(axes); return msWCSException(map, "InvalidParameterValue", "extent", params->version); @@ -4210,6 +4292,8 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p /* if the subsets have a crs given, project the image extent to it */ msInitProjection(&subsetProj); if(msLoadProjectionString(&subsetProj, params->subsetcrs) != MS_SUCCESS) { + msFreeProjection(&subsetProj); + msFreeProjection(&imageProj); msWCSClearCoverageMetadata20(&cm); msSetError(MS_WCSERR, "Error loading CRS %s.", @@ -4219,6 +4303,42 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p } if(msProjectionsDiffer(&imageProj, &subsetProj)) { +#ifdef USE_PROJ + /* Reprojection of source raster extent of (-180,-90,180,90) to any */ + /* projected CRS is going to exhibit strong anomalies. So instead */ + /* do the reverse, project the subset extent to the layer CRS, and */ + /* see how much the subset extent takes with respect to the source */ + /* raster extent. This is only used if output width and resolutionX (or */ + /* (height and resolutionY) are unknown. */ + if( ((params->width == 0 && params->resolutionX == MS_WCS20_UNBOUNDED) || + (params->height == 0 && params->resolutionY == MS_WCS20_UNBOUNDED)) && + (pj_is_latlong(imageProj.proj) && + !pj_is_latlong(subsetProj.proj) && + fabs(layer->extent.minx - -180.0) < 1e-5 && + fabs(layer->extent.miny - -90.0) < 1e-5 && + fabs(layer->extent.maxx - 180.0) < 1e-5 && + fabs(layer->extent.maxy - 90.0) < 1e-5) ) + { + rectObj subsetInImageProj = subsets; + if( msProjectRect(&subsetProj, &imageProj, &(subsetInImageProj)) == MS_SUCCESS ) + { + subsetInImageProj.minx = MS_MAX(subsetInImageProj.minx, layer->extent.minx); + subsetInImageProj.miny = MS_MAX(subsetInImageProj.miny, layer->extent.miny); + subsetInImageProj.maxx = MS_MIN(subsetInImageProj.maxx, layer->extent.maxx); + subsetInImageProj.maxy = MS_MIN(subsetInImageProj.maxy, layer->extent.maxy); + { + double total = ABS(layer->extent.maxx - layer->extent.minx); + double part = ABS(subsetInImageProj.maxx - subsetInImageProj.minx); + widthFromComputationInImageCRS = MS_NINT((part * map->width) / total); + } + { + double total = ABS(layer->extent.maxy - layer->extent.miny); + double part = ABS(subsetInImageProj.maxy - subsetInImageProj.miny); + heightFromComputationInImageCRS = MS_NINT((part * map->height) / total); + } + } + } +#endif msProjectRect(&imageProj, &subsetProj, &(layer->extent)); map->extent = layer->extent; msFreeProjection(&(map->projection)); @@ -4269,7 +4389,9 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p } else if(params->resolutionX != MS_WCS20_UNBOUNDED) { params->width = MS_NINT((bbox.maxx - bbox.minx) / params->resolutionX); } else { - if(ABS(bbox.maxx - bbox.minx) != ABS(map->extent.maxx - map->extent.minx)) { + if( widthFromComputationInImageCRS != 0 ) { + params->width = widthFromComputationInImageCRS; + } else if(ABS(bbox.maxx - bbox.minx) != ABS(map->extent.maxx - map->extent.minx)) { double total = ABS(map->extent.maxx - map->extent.minx), part = ABS(bbox.maxx - bbox.minx); params->width = MS_NINT((part * map->width) / total); @@ -4291,7 +4413,9 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p } else if(params->resolutionY != MS_WCS20_UNBOUNDED) { params->height = MS_NINT((bbox.maxy - bbox.miny) / params->resolutionY); } else { - if(ABS(bbox.maxy - bbox.miny) != ABS(map->extent.maxy - map->extent.miny)) { + if( heightFromComputationInImageCRS != 0 ) { + params->height = heightFromComputationInImageCRS; + } else if(ABS(bbox.maxy - bbox.miny) != ABS(map->extent.maxy - map->extent.miny)) { double total = ABS(map->extent.maxy - map->extent.miny), part = ABS(bbox.maxy - bbox.miny); params->height = MS_NINT((part * map->height) / total); @@ -4336,6 +4460,9 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p params->resolutionX = (bbox.maxx - bbox.minx) / params->width; params->resolutionY = (bbox.maxy - bbox.miny) / params->height; } + else { + msFreeProjection(&outputProj); + } } /* set the bounding box as new map extent */ diff --git a/mapwfs.c b/mapwfs.c index 68dc8df7be..c2145d8492 100644 --- a/mapwfs.c +++ b/mapwfs.c @@ -37,6 +37,7 @@ /* There is a dependency to GDAL/OGR for the GML driver and MiniXML parser */ #include "cpl_minixml.h" #include "cpl_conv.h" +#include "cpl_string.h" #include "mapogcfilter.h" #include "mapowscommon.h" @@ -2065,6 +2066,8 @@ static int msWFSRunFilter(mapObj* map, return msWFSException(map, "mapserv", MS_OWS_ERROR_NO_APPLICABLE_CODE, paramsObj->pszVersion); } + FLTProcessPropertyIsNull(psNode, map, lp->index); + /*preparse the filter for gml aliases*/ FLTPreParseFilterForAliasAndGroup(psNode, map, lp->index, "G"); @@ -2136,6 +2139,7 @@ static int msWFSRunBasicGetFeature(mapObj* map, const char *pszMapSRS=NULL, *pszLayerSRS=NULL; rectObj ext; int status; + const char* pszUseDefaultExtent; map->query.type = MS_QUERY_BY_RECT; /* setup the query */ map->query.mode = MS_QUERY_MULTIPLE; @@ -2147,7 +2151,15 @@ static int msWFSRunBasicGetFeature(mapObj* map, if(!paramsObj->pszSrs) pszMapSRS = msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FO", MS_TRUE); - if (msOWSGetLayerExtent(map, lp, "FO", &ext) == MS_SUCCESS) { + pszUseDefaultExtent = msOWSLookupMetadata(&(lp->metadata), "F", + "use_default_extent_for_getfeature"); + if( pszUseDefaultExtent && !CSLTestBoolean(pszUseDefaultExtent) && + lp->connectiontype == MS_OGR ) + { + const rectObj rectInvalid = MS_INIT_INVALID_RECT; + map->query.rect = rectInvalid; + } + else if (msOWSGetLayerExtent(map, lp, "FO", &ext) == MS_SUCCESS) { /* For a single point layer, to avoid numerical precision issues */ /* when reprojection is involved */ @@ -3813,13 +3825,25 @@ int msWFSGetFeature(mapObj *map, wfsParamsObj *paramsObj, cgiRequestObj *req, } } + { + int i; + for(i=0;inumlayers;i++) + { + layerObj* lp = GET_LAYER(map, i); + if( papszGMLGroups[i] ) + msInsertHashTable(&(lp->metadata), "GML_GROUPS", papszGMLGroups[i]); + if( papszGMLIncludeItems[i] ) + msInsertHashTable(&(lp->metadata), "GML_INCLUDE_ITEMS", papszGMLIncludeItems[i]); + if( papszGMLGeometries[i] ) + msInsertHashTable(&(lp->metadata), "GML_GEOMETRIES", papszGMLGeometries[i]); + } + } + /* handle case of maxfeatures = 0 */ /*internally use a start index that start with 0 as the first index*/ if( psFormat == NULL ) { if(maxfeatures != 0 && iResultTypeHits == 0) { - layerObj* lp; - int i; int bWFS2MultipleFeatureCollection = MS_FALSE; /* Would make sense for WFS 1.1.0 too ! See #3576 */ @@ -3830,24 +3854,14 @@ int msWFSGetFeature(mapObj *map, wfsParamsObj *paramsObj, cgiRequestObj *req, else if (useurn && strcasecmp(useurn, "false") == 0) bUseURN = 0; - for(i=0;inumlayers;i++) - { - lp = GET_LAYER(map, i); - if( papszGMLGroups[i] ) - msInsertHashTable(&(lp->metadata), "GML_GROUPS", papszGMLGroups[i]); - if( papszGMLIncludeItems[i] ) - msInsertHashTable(&(lp->metadata), "GML_INCLUDE_ITEMS", papszGMLIncludeItems[i]); - if( papszGMLGeometries[i] ) - msInsertHashTable(&(lp->metadata), "GML_GEOMETRIES", papszGMLGeometries[i]); - } - /* For WFS 2.0, when we request several types, we must present each type */ /* in its own FeatureCollection (§ 11.3.3.5 ) */ if( nWFSVersion >= OWS_2_0_0 && iResultTypeHits != 1 ) { + int i; int nLayersWithFeatures = 0; for(i=0; inumlayers; i++) { - lp = GET_LAYER(map, i); + layerObj* lp = GET_LAYER(map, i); if(lp->resultcache && lp->resultcache->numresults > 0) nLayersWithFeatures ++; } @@ -3866,7 +3880,7 @@ int msWFSGetFeature(mapObj *map, wfsParamsObj *paramsObj, cgiRequestObj *req, /* Save the result cache that contains the features that we want to */ /* emit in the response */ for(i=0; inumlayers; i++) { - lp = GET_LAYER(map, i); + layerObj* lp = GET_LAYER(map, i); saveResultCache[i] = lp->resultcache; if( lp->resultcache && lp->resultcache->numresults > 0) { iLastNonEmptyLayer = i; @@ -3876,7 +3890,7 @@ int msWFSGetFeature(mapObj *map, wfsParamsObj *paramsObj, cgiRequestObj *req, /* Just dump one layer at a time */ for(i=0;inumlayers;i++) { - lp = GET_LAYER(map, i); + layerObj* lp = GET_LAYER(map, i); lp->resultcache = saveResultCache[i]; if( lp->resultcache && lp->resultcache->numresults > 0) { msIO_fprintf(stdout, " \n"); @@ -3901,7 +3915,7 @@ int msWFSGetFeature(mapObj *map, wfsParamsObj *paramsObj, cgiRequestObj *req, /* Restore for later cleanup */ for(i=0; inumlayers; i++) { - lp = GET_LAYER(map, i); + layerObj* lp = GET_LAYER(map, i); lp->resultcache = saveResultCache[i]; } msFree(saveResultCache); @@ -4151,6 +4165,7 @@ int msWFSGetPropertyValue(mapObj *map, wfsParamsObj *paramsObj, cgiRequestObj *r if (z == geometryList->numgeometries) { msSetError(MS_WFSERR, "Invalid VALUEREFERENCE %s", "msWFSGetPropertyValue()", paramsObj->pszValueReference); + msFree(pszGMLGroups); msGMLFreeItems(itemList); msGMLFreeGroups(groupList); msGMLFreeGeometries(geometryList); @@ -4219,8 +4234,12 @@ int msWFSGetPropertyValue(mapObj *map, wfsParamsObj *paramsObj, cgiRequestObj *r &maxfeatures, &startindex); status = msWFSAnalyzeBBOX(map, paramsObj, &bbox, &sBBoxSrs); - if( status != 0 ) + if( status != 0 ) { + msFree(pszGMLGroups); + msFree(pszGMLIncludeItems); + msFree(pszGMLGeometries); return status; + } if( iResultTypeHits == 1 ) { diff --git a/mapwfs11.c b/mapwfs11.c index 20ab1644ea..16077bb228 100644 --- a/mapwfs11.c +++ b/mapwfs11.c @@ -119,10 +119,10 @@ xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws, valueToFree = (char *) msSmallMalloc(sizeof(char*)*n); snprintf(valueToFree, n, "%s%s%s", (value ? value : ""), (value ? ":" : ""), lp->name); - psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Name", BAD_CAST valueToFree); + psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "Name", BAD_CAST valueToFree); msFree(valueToFree); } else { - psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Name", BAD_CAST lp->name); + psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "Name", BAD_CAST lp->name); } if (lp->name && strlen(lp->name) > 0 && @@ -140,12 +140,12 @@ xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws, if (!value) value =(const char*)lp->name; - psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Title", BAD_CAST value); + psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "Title", BAD_CAST value); value = msOWSLookupMetadataWithLanguage(&(lp->metadata), "FO", "abstract", validate_language); if (value) - psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Abstract", BAD_CAST value); + psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "Abstract", BAD_CAST value); @@ -165,15 +165,15 @@ xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws, tokens = msStringSplit(valueToFree, ' ', &n); if (tokens && n > 0) { if( nWFSVersion == OWS_1_1_0 ) - psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultSRS", BAD_CAST tokens[0]); + psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "DefaultSRS", BAD_CAST tokens[0]); else - psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultCRS", BAD_CAST tokens[0]); + psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "DefaultCRS", BAD_CAST tokens[0]); for (i=1; imetadata), "FO", "metadataurl_format"); diff --git a/mapwfs20.c b/mapwfs20.c index 710d4441de..50da8443e6 100644 --- a/mapwfs20.c +++ b/mapwfs20.c @@ -163,7 +163,7 @@ xmlNodePtr msWFSConstraintDefaultValue(xmlNsPtr psNs, xmlNsPtr psNsOws, const ch xmlNewProp(psRootNode, BAD_CAST "name", BAD_CAST name); xmlNewChild(psRootNode, psNsOws, BAD_CAST "NoValues", NULL ); - xmlNewChild(psRootNode, psNsOws, BAD_CAST "DefaultValue", BAD_CAST value); + xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "DefaultValue", BAD_CAST value); return psRootNode; } @@ -334,9 +334,9 @@ static void msWFSAddInspireDSID(mapObj *map, { xmlNodePtr pSDSI = xmlNewNode(psNsInspireDls, BAD_CAST "SpatialDataSetIdentifier"); xmlAddChild(pDlsExtendedCapabilities, pSDSI); - xmlNewChild(pSDSI, psNsInspireCommon, BAD_CAST "Code", BAD_CAST tokensCode[i]); + xmlNewTextChild(pSDSI, psNsInspireCommon, BAD_CAST "Code", BAD_CAST tokensCode[i]); if( ntokensNS > 0 && tokensNS[i][0] != '\0' ) - xmlNewChild(pSDSI, psNsInspireCommon, BAD_CAST "Namespace", BAD_CAST tokensNS[i]); + xmlNewTextChild(pSDSI, psNsInspireCommon, BAD_CAST "Namespace", BAD_CAST tokensNS[i]); } msFreeCharArray(tokensCode, ntokensCode); if( ntokensNS > 0 ) @@ -824,15 +824,44 @@ static char* msWFSGetStoredQuery(mapObj *map, const char* pszURN) FILE* f = fopen(value, "rb"); if( f != NULL ) { - char* pszBuffer = (char*) msSmallMalloc(32000); - int nread = fread(pszBuffer, 1, 32000-1, f); - fclose(f); - if( nread > 0 ) + char* pszBuffer; + int nread; + long length; + + fseek(f, 0, SEEK_END); + length = ftell(f); + if( length > 1000000 ) + { + msSetError(MS_WFSERR, "%s: too big (%ld bytes > 1000000)", + "msWFSGetStoredQuery()", value, length); + fclose(f); + } + else { - pszBuffer[nread-1] = '\0'; - return pszBuffer; + fseek(f, 0, SEEK_SET); + pszBuffer = (char*) malloc((int)length + 1); + if( pszBuffer == NULL ) + { + msSetError(MS_WFSERR, "Cannot allocate %d bytes to read %s", + "msWFSGetStoredQuery()", + (int)length + 1, value); + fclose(f); + } + else + { + nread = (int)fread(pszBuffer, 1, length, f); + fclose(f); + if( nread == length ) + { + pszBuffer[nread] = '\0'; + return pszBuffer; + } + msSetError(MS_WFSERR, "Could only read %d bytes / %d of %s", + "msWFSGetStoredQuery()", + nread, (int)length, value); + msFree(pszBuffer); + } } - msFree(pszBuffer); } else { diff --git a/mapwfslayer.c b/mapwfslayer.c index fe6560ee10..4a30955bb4 100644 --- a/mapwfslayer.c +++ b/mapwfslayer.c @@ -445,7 +445,7 @@ static char *msBuildWFSLayerGetURL(mapObj *map, layerObj *lp, rectObj *bbox, } else { snprintf(pszURL + strlen(pszURL), bufferSize - strlen(pszURL), "&BBOX=%.15g,%.15g,%.15g,%.15g,%s&SRSNAME=%s", - bbox->minx, bbox->miny, bbox->maxy, bbox->maxy, + bbox->minx, bbox->miny, bbox->maxx, bbox->maxy, projUrn, projUrn); } } else { diff --git a/mapwms.c b/mapwms.c index 6dc4ebfe4c..1b0910926b 100644 --- a/mapwms.c +++ b/mapwms.c @@ -791,7 +791,6 @@ int msWMSLoadGetMapParams(mapObj *map, int nVersion, const char *wms_request, owsRequestObj *ows_request) { int i, adjust_extent = MS_FALSE, nonsquare_enabled = MS_FALSE; - int nLayerOrder = 0; int transparent = MS_NOOVERRIDE; int bbox_pixel_is_point = MS_FALSE; outputFormatObj *format = NULL; @@ -870,6 +869,7 @@ int msWMSLoadGetMapParams(mapObj *map, int nVersion, if (strcasecmp(names[i], "LAYERS") == 0) { int j, k, iLayer, *layerOrder; + int nLayerOrder = 0; char ***nestedGroups = NULL; int *numNestedGroups = NULL; int *isUsedInNestedGroup = NULL; diff --git a/mapwmslayer.c b/mapwmslayer.c index 3e4747dd57..3150522382 100644 --- a/mapwmslayer.c +++ b/mapwmslayer.c @@ -1452,15 +1452,16 @@ int msWMSLayerExecuteRequest(mapObj *map, int nOWSLayers, int nClickX, int nClic /* Generate the http request */ for (i=0; inumlayers; i++) { if (GET_LAYER(map,map->layerorder[i])->status == MS_ON) { - if (type == WMS_GETFEATUREINFO && - msPrepareWMSLayerRequest(map->layerorder[i], map, GET_LAYER(map,map->layerorder[i]), + if (type == WMS_GETFEATUREINFO ) { + if( msPrepareWMSLayerRequest(map->layerorder[i], map, GET_LAYER(map,map->layerorder[i]), WMS_GETFEATUREINFO, MS_WMS, &sLastWMSParams, nClickX, nClickY, nFeatureCount, pszInfoFormat, pasReqInfo, &numReq) == MS_FAILURE) { - msFreeWmsParamsObj(&sLastWMSParams); - msFree(pasReqInfo); - return MS_FAILURE; + msFreeWmsParamsObj(&sLastWMSParams); + msFree(pasReqInfo); + return MS_FAILURE; + } } else if (msPrepareWMSLayerRequest(map->layerorder[i], map, GET_LAYER(map,map->layerorder[i]), WMS_GETLEGENDGRAPHIC, MS_WMS, &sLastWMSParams, diff --git a/msautotest/README b/msautotest/README index fe25a807d2..e83faf0958 100644 --- a/msautotest/README +++ b/msautotest/README @@ -2,4 +2,5 @@ See: http://www.mapserver.org/development/tests/autotest.html -Send new tests via MapServer Issue Tracker (component MSAutoTest). +Send new tests via MapServer Issue Tracker at https://github.com/mapserver/mapserver/issues/ +(use the label 'Msautotest'). diff --git a/msautotest/create_postgis_test_data.bat b/msautotest/create_postgis_test_data.bat new file mode 100644 index 0000000000..7f6256cb8f --- /dev/null +++ b/msautotest/create_postgis_test_data.bat @@ -0,0 +1,49 @@ +REM Load PostgreSQL/PostGIS data for msautotest, on windows + +SET PGPASSWORD=postgres +set PG-PORT=5433 + +psql -c "drop database if exists msautotest" -U postgres -p %PG-PORT% +psql -c "create database msautotest" -U postgres -p %PG-PORT% +psql -c "create extension postgis" -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -g the_geom query/data/bdry_counpy2.shp bdry_counpy2 | psql -U postgres -d msautotest -p %PG-PORT% +shp2pgsql -g the_geom -s 3978 wxs/data/popplace.shp popplace | psql -U postgres -d msautotest -p %PG-PORT% +shp2pgsql -g the_geom -s 3978 wxs/data/province.shp province | psql -U postgres -d msautotest -p %PG-PORT% +shp2pgsql -g the_geom -s 3978 wxs/data/road.shp road| psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern1.shp pattern1 | psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern2.shp pattern2 | psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern3.shp pattern3 | psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern4.shp pattern4 | psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern5.shp pattern5 | psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern6.shp pattern6 | psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern7.shp pattern7 | psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern8.shp pattern8 | psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern9.shp pattern9 | psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern10.shp pattern10 | psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern11.shp pattern11 | psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern12.shp pattern12 | psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern13.shp pattern13 | psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern14.shp pattern14 | psql -d msautotest -U postgres -p %PG-PORT% +shp2pgsql -s 4326 -g the_geom wxs/data/pattern15.shp pattern15 | psql -d msautotest -U postgres -p %PG-PORT% + +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern1 RENAME COLUMN time to time_str; alter TABLE pattern1 ADD COLUMN time timestamp without time zone; update pattern1 set time = to_timestamp(time_str,'YYYYMMDD');" +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern2 RENAME COLUMN time to time_str; alter TABLE pattern2 ADD COLUMN time timestamp without time zone; update pattern2 set time = to_timestamp(time_str,'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"');" +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern3 RENAME COLUMN time to time_str; alter TABLE pattern3 ADD COLUMN time timestamp without time zone; update pattern3 set time = to_timestamp(time_str,'YYYY-MM-DD\"T\"HH24:MI:SS');" +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern4 RENAME COLUMN time to time_str; alter TABLE pattern4 ADD COLUMN time timestamp without time zone; update pattern4 set time = to_timestamp(time_str,'YYYY-MM-DD HH24:MI:SS');" +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern5 RENAME COLUMN time to time_str; alter TABLE pattern5 ADD COLUMN time timestamp without time zone; update pattern5 set time = to_timestamp(time_str,'YYYY-MM-DD\"T\"HH24:MI');" +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern6 RENAME COLUMN time to time_str; alter TABLE pattern6 ADD COLUMN time timestamp without time zone; update pattern6 set time = to_timestamp(time_str,'YYYY-MM-DD HH24:MI');" +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern7 RENAME COLUMN time to time_str; alter TABLE pattern7 ADD COLUMN time timestamp without time zone; update pattern7 set time = to_timestamp(time_str,'YYYY-MM-DD\"T\"HH24');" +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern8 RENAME COLUMN time to time_str; alter TABLE pattern8 ADD COLUMN time timestamp without time zone; update pattern8 set time = to_timestamp(time_str,'YYYY-MM-DD HH24');" +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern9 RENAME COLUMN time to time_str; alter TABLE pattern9 ADD COLUMN time timestamp without time zone; update pattern9 set time = to_timestamp(time_str,'YYYY-MM-DD');" +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern10 RENAME COLUMN time to time_str; alter TABLE pattern10 ADD COLUMN time timestamp without time zone; update pattern10 set time = to_timestamp(time_str,'YYYY-MM');" +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern11 RENAME COLUMN time to time_str; alter TABLE pattern11 ADD COLUMN time timestamp without time zone; update pattern11 set time = to_timestamp(time_str,'YYYY');" +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern12 RENAME COLUMN time to time_str; alter TABLE pattern12 ADD COLUMN time time without time zone; update pattern12 set time = to_timestamp(time_str,'\"T\"HH24:MI:SSZ')::time;" +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern13 RENAME COLUMN time to time_str; alter TABLE pattern13 ADD COLUMN time time without time zone; update pattern13 set time = to_timestamp(time_str,'THH24:MI:SS')::time;" +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern14 RENAME COLUMN time to time_str; alter TABLE pattern14 ADD COLUMN time timestamp without time zone; update pattern14 set time = to_timestamp(time_str,'YYYY-MM-DD HH24:MI:SSZ');" +psql -U postgres -d msautotest -p %PG-PORT% -c "alter TABLE pattern15 RENAME COLUMN time to time_str; alter TABLE pattern15 ADD COLUMN time timestamp without time zone; update pattern15 set time = to_timestamp(time_str,'YYYY-MM-DDZ');" +psql -U postgres -d msautotest -p %PG-PORT% -c "CREATE TABLE point3d (ID SERIAL); SELECT AddGeometryColumn('public', 'point3d', 'the_geom', 27700, 'POINT', 3); INSERT INTO point3d (the_geom) VALUES (GeomFromEWKT('SRID=27700;POINT(1 2 3)'));" +psql -U postgres -d msautotest -p %PG-PORT% -c "CREATE TABLE multipoint3d (ID SERIAL); SELECT AddGeometryColumn('public', 'multipoint3d', 'the_geom', 27700, 'MULTIPOINT', 3); INSERT INTO multipoint3d (the_geom) VALUES (GeomFromEWKT('SRID=27700;MULTIPOINT(1 2 3,4 5 6)'));" +psql -U postgres -d msautotest -p %PG-PORT% -c "CREATE TABLE linestring3d (ID SERIAL); SELECT AddGeometryColumn('public', 'linestring3d', 'the_geom', 27700, 'LINESTRING', 3); INSERT INTO linestring3d (the_geom) VALUES (GeomFromEWKT('SRID=27700;LINESTRING(1 2 3,4 5 6)'));" +psql -U postgres -d msautotest -p %PG-PORT% -c "CREATE TABLE multilinestring3d (ID SERIAL); SELECT AddGeometryColumn('public', 'multilinestring3d', 'the_geom', 27700, 'MULTILINESTRING', 3); INSERT INTO multilinestring3d (the_geom) VALUES (GeomFromEWKT('SRID=27700;MULTILINESTRING((1 2 3,4 5 6),(7 8 9,10 11 12))'));" +psql -U postgres -d msautotest -p %PG-PORT% -c "CREATE TABLE polygon3d (ID SERIAL); SELECT AddGeometryColumn('public', 'polygon3d', 'the_geom', 27700, 'POLYGON', 3); INSERT INTO polygon3d (the_geom) VALUES (GeomFromEWKT('SRID=27700;POLYGON((0 0 1,10 0 2,10 10 3,0 10 4,0 0 1))')); INSERT INTO polygon3d (the_geom) VALUES (GeomFromEWKT('SRID=27700;POLYGON((0 0 1,10 0 2,10 10 3,0 10 4,0 0 1),(1 1 2,1 9 3,9 9 4,9 1 5,1 1 2))'));" +psql -U postgres -d msautotest -p %PG-PORT% -c "CREATE TABLE multipolygon3d (ID SERIAL); SELECT AddGeometryColumn('public', 'multipolygon3d', 'the_geom', 27700, 'MULTIPOLYGON', 3); INSERT INTO multipolygon3d (the_geom) VALUES (GeomFromEWKT('SRID=27700;MULTIPOLYGON(((0 0 1,10 0 2,10 10 3,0 10 4,0 0 1),(1 1 2,1 9 3,9 9 4,9 1 5,1 1 2)),((10 10 0,10 20 1,20 20 2,20 10 3,10 10 0)))'));" diff --git a/msautotest/gdal/data/lon_wrap_180.asc b/msautotest/gdal/data/lon_wrap_180.asc new file mode 100644 index 0000000000..fa82f27009 --- /dev/null +++ b/msautotest/gdal/data/lon_wrap_180.asc @@ -0,0 +1,25 @@ +ncols 40 +nrows 20 +xllcorner -0.1 +yllcorner -90.000000000000 +cellsize 9.000000000000 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 + 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 127 diff --git a/msautotest/gdal/data/lon_wrap_180.prj b/msautotest/gdal/data/lon_wrap_180.prj new file mode 100644 index 0000000000..a30c00a55d --- /dev/null +++ b/msautotest/gdal/data/lon_wrap_180.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] \ No newline at end of file diff --git a/msautotest/gdal/expected/average_rgb.png b/msautotest/gdal/expected/average_rgb.png index b23e7d06cd..672997817f 100644 Binary files a/msautotest/gdal/expected/average_rgb.png and b/msautotest/gdal/expected/average_rgb.png differ diff --git a/msautotest/gdal/expected/average_rgb_plug.png b/msautotest/gdal/expected/average_rgb_plug.png index b23e7d06cd..672997817f 100644 Binary files a/msautotest/gdal/expected/average_rgb_plug.png and b/msautotest/gdal/expected/average_rgb_plug.png differ diff --git a/msautotest/gdal/expected/lon_wrap_180.png b/msautotest/gdal/expected/lon_wrap_180.png new file mode 100644 index 0000000000..e5f7b50638 Binary files /dev/null and b/msautotest/gdal/expected/lon_wrap_180.png differ diff --git a/msautotest/gdal/expected/wmsclient_3543.png b/msautotest/gdal/expected/wmsclient_3543.png index c0612b6b37..418f92181d 100644 Binary files a/msautotest/gdal/expected/wmsclient_3543.png and b/msautotest/gdal/expected/wmsclient_3543.png differ diff --git a/msautotest/gdal/heat.map b/msautotest/gdal/heat.map index fb3afec038..b29280a59f 100644 --- a/msautotest/gdal/heat.map +++ b/msautotest/gdal/heat.map @@ -92,26 +92,26 @@ layer type POINT data "data/pnts.shp" CLASS - MAXSCALE 255000000 + MAXSCALEDENOM 255000000 STYLE SIZE [VAL] END END CLASS - MAXSCALE 265000000 + MAXSCALEDENOM 265000000 STYLE SIZE 0.1 END END CLASS - MAXSCALE 275000000 + MAXSCALEDENOM 275000000 EXPRESSION ([VAL]>1) STYLE SIZE 1 END END CLASS - MAXSCALE 275000000 + MAXSCALEDENOM 275000000 STYLE SIZE 2 END diff --git a/msautotest/gdal/lon_wrap_180.map b/msautotest/gdal/lon_wrap_180.map new file mode 100644 index 0000000000..c09e6fb4b4 --- /dev/null +++ b/msautotest/gdal/lon_wrap_180.map @@ -0,0 +1,36 @@ +# Test behaviour with a projection with lon_wrap=180 + +MAP + +NAME TEST +STATUS ON +SIZE 40 20 +EXTENT -180 -89.9999 180 90 +IMAGECOLOR 0 0 0 + + PROJECTION + "init=epsg:4326" + END + +OUTPUTFORMAT + NAME "png" + DRIVER AGG/PNG + MIMETYPE "image/png" + IMAGEMODE RGBA + EXTENSION "png" +END + +LAYER + NAME test + TYPE RASTER + STATUS default + DATA "data/lon_wrap_180.asc" + PROJECTION + "proj=longlat" + "datum=WGS84" + "lon_wrap=180" + "no_defs" + END +END + +END # of map file diff --git a/msautotest/misc/expected/grid_without_label.png b/msautotest/misc/expected/grid_without_label.png new file mode 100644 index 0000000000..9f4f0a4571 Binary files /dev/null and b/msautotest/misc/expected/grid_without_label.png differ diff --git a/msautotest/misc/expected/runtime_sub_test012.png b/msautotest/misc/expected/runtime_sub_test012.png index 5a765a23c7..6c815558db 100644 Binary files a/msautotest/misc/expected/runtime_sub_test012.png and b/msautotest/misc/expected/runtime_sub_test012.png differ diff --git a/msautotest/misc/expected/runtime_sub_test013.png b/msautotest/misc/expected/runtime_sub_test013.png index bb2286edb4..7f06ece301 100644 Binary files a/msautotest/misc/expected/runtime_sub_test013.png and b/msautotest/misc/expected/runtime_sub_test013.png differ diff --git a/msautotest/misc/expected/runtime_sub_test_caps.xml b/msautotest/misc/expected/runtime_sub_test_caps.xml index a97cd44cb3..8e1f4c2acd 100644 --- a/msautotest/misc/expected/runtime_sub_test_caps.xml +++ b/msautotest/misc/expected/runtime_sub_test_caps.xml @@ -10,8 +10,8 @@ Content-Type: text/xml; charset=UTF-8 - 2048 - 2048 + 4096 + 4096 diff --git a/msautotest/misc/grid_without_label.map b/msautotest/misc/grid_without_label.map new file mode 100644 index 0000000000..a9c39fd173 --- /dev/null +++ b/msautotest/misc/grid_without_label.map @@ -0,0 +1,38 @@ +# +# REQUIRES: OUTPUT=PNG SUPPORTS=PROJ +# + +MAP + NAME "testMap" + + STATUS ON + SIZE 200 100 + EXTENT 0 0 2000 1000 + UNITS METERS + IMAGETYPE png + + PROJECTION + "init=epsg:3857" + END + + LAYER + NAME "grid" + PROJECTION + "init=epsg:3857" + END + STATUS ON + TYPE LINE + UNITS METERS + CLASS + STYLE + COLOR "#000000" + OPACITY 100 + END + END + GRID + MAXINTERVAL 500 + MININTERVAL 500 + END + END + +END diff --git a/msautotest/misc/scaletoken.map b/msautotest/misc/scaletoken.map index 9819092777..60296620ec 100644 --- a/msautotest/misc/scaletoken.map +++ b/msautotest/misc/scaletoken.map @@ -17,13 +17,13 @@ MAP SHAPEPATH "." IMAGETYPE PNG - #DEBUG 10 + #DEBUG 1 #CONFIG "MS_ERRORFILE" "stderr" LAYER NAME 'layer1' STATUS ON - DEBUG 10 + DEBUG 1 SCALETOKEN NAME "%shpfile%" VALUES @@ -41,7 +41,7 @@ MAP LAYER NAME 'layer2' STATUS ON - DEBUG 10 + DEBUG 1 DATA "data/shppoly/poly.shp" SCALETOKEN NAME "%filter%" @@ -60,7 +60,7 @@ MAP LAYER NAME 'layer3' STATUS ON - DEBUG 10 + DEBUG 1 DATA "data/shppoly/poly.shp" SCALETOKEN NAME "%filteritem%" diff --git a/msautotest/mspython/test_mapio.map b/msautotest/mspython/test_mapio.map new file mode 100644 index 0000000000..d25adb98e4 --- /dev/null +++ b/msautotest/mspython/test_mapio.map @@ -0,0 +1,35 @@ +# REQUIRES: INPUT=GDAL OUTPUT=PNG SUPPORTS=WMS +# +MAP +NAME TEST +STATUS ON +SIZE 80 40 +EXTENT -180 -90 180 90 + +PROJECTION + "init=epsg:4326" +END + +OUTPUTFORMAT + NAME png24_t + DRIVER "GDAL/PNG" + IMAGEMODE RGBA +END + +WEB + METADATA + "ows_enable_request" "*" + "wms_srs" "EPSG:4326" + "ows_http_max_age" "86400" + END +END + +LAYER + NAME grey + TYPE raster + STATUS default + DATA ../gdal/data/grey.tif +END + + +END # of map file diff --git a/msautotest/mspython/test_mapio.py b/msautotest/mspython/test_mapio.py new file mode 100755 index 0000000000..ed26b663aa --- /dev/null +++ b/msautotest/mspython/test_mapio.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +############################################################################### +# $Id$ +# +# Project: MapServer +# Purpose: Regression test for mapio +# Author: Even Rouault +# +############################################################################### +# Copyright (c) 2017, Even Rouault, +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +############################################################################### + +import sys +import string + +sys.path.append( '../pymod' ) +import pmstestlib + +import mapscript +import os + +############################################################################### +# + +def test_msIO_getAndStripStdoutBufferMimeHeaders(): + + if string.find(mapscript.msGetVersion(),'INPUT=GDAL') == -1: + return 'skip' + if string.find(mapscript.msGetVersion(),'SUPPORTS=WMS') == -1: + return 'skip' + + map = mapscript.mapObj('test_mapio.map') + request = mapscript.OWSRequest() + mapscript.msIO_installStdoutToBuffer() + request.loadParamsFromURL('service=WMS&version=1.1.1&request=GetMap&layers=grey&srs=EPSG:4326&bbox=-180,-90,180,90&format=image/png&width=80&height=40') + status = map.OWSDispatch(request) + if status != 0: + pmstestlib.post_reason( 'wrong OWSDispatch status' ) + return 'fail' + headers = mapscript.msIO_getAndStripStdoutBufferMimeHeaders() + if headers is None: + pmstestlib.post_reason( 'headers is None' ) + return 'fail' + if 'Content-Type' not in headers or headers['Content-Type'] != 'image/png': + pmstestlib.post_reason( 'wrong Content-Type' ) + print(headers) + return 'fail' + if 'Cache-Control' not in headers or headers['Cache-Control'] != 'max-age=86400': + pmstestlib.post_reason( 'wrong Cache-Control' ) + print(headers) + return 'fail' + + result = mapscript.msIO_getStdoutBufferBytes() + if result is None or result[1:4] != 'PNG': + pmstestlib.post_reason( 'wrong data' ) + return 'fail' + + return 'success' + +test_list = [ + test_msIO_getAndStripStdoutBufferMimeHeaders, + None ] + +if __name__ == '__main__': + + pmstestlib.setup_run( 'test_mapio' ) + + pmstestlib.run_tests( test_list ) + + pmstestlib.summarize() + + mapscript.msCleanup() + diff --git a/msautotest/renderers/data/DejaVuSansCondensed.ttf b/msautotest/renderers/data/DejaVuSansCondensed.ttf new file mode 100644 index 0000000000..c9e4acec8c Binary files /dev/null and b/msautotest/renderers/data/DejaVuSansCondensed.ttf differ diff --git a/msautotest/renderers/data/fonts.lst b/msautotest/renderers/data/fonts.lst index 0e6066a87f..c28489eb2d 100644 --- a/msautotest/renderers/data/fonts.lst +++ b/msautotest/renderers/data/fonts.lst @@ -1,2 +1,3 @@ default ../../misc/data/LucidaBrightRegular.ttf cjk VL-Gothic-Regular.ttf +dejavu DejaVuSansCondensed.ttf diff --git a/msautotest/renderers/data/meteo.dbf b/msautotest/renderers/data/meteo.dbf new file mode 100644 index 0000000000..1199009835 Binary files /dev/null and b/msautotest/renderers/data/meteo.dbf differ diff --git a/msautotest/renderers/data/meteo.prj b/msautotest/renderers/data/meteo.prj new file mode 100644 index 0000000000..a30c00a55d --- /dev/null +++ b/msautotest/renderers/data/meteo.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] \ No newline at end of file diff --git a/msautotest/renderers/data/meteo.shp b/msautotest/renderers/data/meteo.shp new file mode 100644 index 0000000000..7a9d6ef0b8 Binary files /dev/null and b/msautotest/renderers/data/meteo.shp differ diff --git a/msautotest/renderers/data/meteo.shx b/msautotest/renderers/data/meteo.shx new file mode 100644 index 0000000000..b666ab799a Binary files /dev/null and b/msautotest/renderers/data/meteo.shx differ diff --git a/msautotest/renderers/expected/average_rgb.cairo.png b/msautotest/renderers/expected/average_rgb.cairo.png index b23e7d06cd..672997817f 100644 Binary files a/msautotest/renderers/expected/average_rgb.cairo.png and b/msautotest/renderers/expected/average_rgb.cairo.png differ diff --git a/msautotest/renderers/expected/average_rgb.pdf b/msautotest/renderers/expected/average_rgb.pdf index d4b09db163..2a0b566457 100644 Binary files a/msautotest/renderers/expected/average_rgb.pdf and b/msautotest/renderers/expected/average_rgb.pdf differ diff --git a/msautotest/renderers/expected/average_rgb.png b/msautotest/renderers/expected/average_rgb.png index b23e7d06cd..672997817f 100644 Binary files a/msautotest/renderers/expected/average_rgb.png and b/msautotest/renderers/expected/average_rgb.png differ diff --git a/msautotest/renderers/expected/average_rgb.svg b/msautotest/renderers/expected/average_rgb.svg index 7ad412cd9b..acb2ba486f 100644 --- a/msautotest/renderers/expected/average_rgb.svg +++ b/msautotest/renderers/expected/average_rgb.svg @@ -1,7 +1,7 @@ - + diff --git a/msautotest/renderers/expected/legend_label_offset.cairo.png b/msautotest/renderers/expected/legend_label_offset.cairo.png new file mode 100644 index 0000000000..23c3bf83b2 Binary files /dev/null and b/msautotest/renderers/expected/legend_label_offset.cairo.png differ diff --git a/msautotest/renderers/expected/legend_label_offset.pdf b/msautotest/renderers/expected/legend_label_offset.pdf new file mode 100644 index 0000000000..745962862c Binary files /dev/null and b/msautotest/renderers/expected/legend_label_offset.pdf differ diff --git a/msautotest/renderers/expected/legend_label_offset.png b/msautotest/renderers/expected/legend_label_offset.png new file mode 100644 index 0000000000..bd70982437 Binary files /dev/null and b/msautotest/renderers/expected/legend_label_offset.png differ diff --git a/msautotest/renderers/expected/legend_label_offset.svg b/msautotest/renderers/expected/legend_label_offset.svg new file mode 100644 index 0000000000..f3ff83788f --- /dev/null +++ b/msautotest/renderers/expected/legend_label_offset.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/msautotest/renderers/expected/legend_raster_gradient.png b/msautotest/renderers/expected/legend_raster_gradient.png new file mode 100644 index 0000000000..d19ec0ef60 Binary files /dev/null and b/msautotest/renderers/expected/legend_raster_gradient.png differ diff --git a/msautotest/renderers/expected/legend_sizeunits_meters.cairo.png b/msautotest/renderers/expected/legend_sizeunits_meters.cairo.png new file mode 100644 index 0000000000..673c92c832 Binary files /dev/null and b/msautotest/renderers/expected/legend_sizeunits_meters.cairo.png differ diff --git a/msautotest/renderers/expected/legend_sizeunits_meters.pdf b/msautotest/renderers/expected/legend_sizeunits_meters.pdf new file mode 100644 index 0000000000..5a68cbbb9c Binary files /dev/null and b/msautotest/renderers/expected/legend_sizeunits_meters.pdf differ diff --git a/msautotest/renderers/expected/legend_sizeunits_meters.png b/msautotest/renderers/expected/legend_sizeunits_meters.png new file mode 100644 index 0000000000..4e32ab4e06 Binary files /dev/null and b/msautotest/renderers/expected/legend_sizeunits_meters.png differ diff --git a/msautotest/renderers/expected/legend_sizeunits_meters.svg b/msautotest/renderers/expected/legend_sizeunits_meters.svg new file mode 100644 index 0000000000..9d7b9e64c9 --- /dev/null +++ b/msautotest/renderers/expected/legend_sizeunits_meters.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/msautotest/renderers/expected/line_marker_svg.png b/msautotest/renderers/expected/line_marker_svg.png index 9dd2794d35..04f00adbbe 100644 Binary files a/msautotest/renderers/expected/line_marker_svg.png and b/msautotest/renderers/expected/line_marker_svg.png differ diff --git a/msautotest/renderers/expected/multilabel-leader.cairo.png b/msautotest/renderers/expected/multilabel-leader.cairo.png new file mode 100644 index 0000000000..e1e20d17d7 Binary files /dev/null and b/msautotest/renderers/expected/multilabel-leader.cairo.png differ diff --git a/msautotest/renderers/expected/multilabel-leader.pdf b/msautotest/renderers/expected/multilabel-leader.pdf new file mode 100644 index 0000000000..63f07c7465 Binary files /dev/null and b/msautotest/renderers/expected/multilabel-leader.pdf differ diff --git a/msautotest/renderers/expected/multilabel-leader.png b/msautotest/renderers/expected/multilabel-leader.png new file mode 100644 index 0000000000..f16cc9c872 Binary files /dev/null and b/msautotest/renderers/expected/multilabel-leader.png differ diff --git a/msautotest/renderers/expected/multilabel-leader.svg b/msautotest/renderers/expected/multilabel-leader.svg new file mode 100644 index 0000000000..87fa8020b4 --- /dev/null +++ b/msautotest/renderers/expected/multilabel-leader.svg @@ -0,0 +1,376 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/msautotest/renderers/expected/point_svg.png b/msautotest/renderers/expected/point_svg.png index 24f1753b6e..c22e1c787a 100644 Binary files a/msautotest/renderers/expected/point_svg.png and b/msautotest/renderers/expected/point_svg.png differ diff --git a/msautotest/renderers/expected/rgb_overlay_res.cairo.png b/msautotest/renderers/expected/rgb_overlay_res.cairo.png index 751ca484b2..f067a7fef7 100644 Binary files a/msautotest/renderers/expected/rgb_overlay_res.cairo.png and b/msautotest/renderers/expected/rgb_overlay_res.cairo.png differ diff --git a/msautotest/renderers/expected/rgb_overlay_res.pdf b/msautotest/renderers/expected/rgb_overlay_res.pdf index 2641adef14..f4077469b6 100644 Binary files a/msautotest/renderers/expected/rgb_overlay_res.pdf and b/msautotest/renderers/expected/rgb_overlay_res.pdf differ diff --git a/msautotest/renderers/expected/rgb_overlay_res.png b/msautotest/renderers/expected/rgb_overlay_res.png index 751ca484b2..f067a7fef7 100644 Binary files a/msautotest/renderers/expected/rgb_overlay_res.png and b/msautotest/renderers/expected/rgb_overlay_res.png differ diff --git a/msautotest/renderers/expected/rgb_overlay_res.svg b/msautotest/renderers/expected/rgb_overlay_res.svg index 05570bafb7..9c2bef8544 100644 --- a/msautotest/renderers/expected/rgb_overlay_res.svg +++ b/msautotest/renderers/expected/rgb_overlay_res.svg @@ -2,7 +2,7 @@ - + diff --git a/msautotest/renderers/expected/rgb_overlay_res_to8bit.cairo.png b/msautotest/renderers/expected/rgb_overlay_res_to8bit.cairo.png index 751ca484b2..f067a7fef7 100644 Binary files a/msautotest/renderers/expected/rgb_overlay_res_to8bit.cairo.png and b/msautotest/renderers/expected/rgb_overlay_res_to8bit.cairo.png differ diff --git a/msautotest/renderers/expected/rgb_overlay_res_to8bit.pdf b/msautotest/renderers/expected/rgb_overlay_res_to8bit.pdf index 2641adef14..f4077469b6 100644 Binary files a/msautotest/renderers/expected/rgb_overlay_res_to8bit.pdf and b/msautotest/renderers/expected/rgb_overlay_res_to8bit.pdf differ diff --git a/msautotest/renderers/expected/rgb_overlay_res_to8bit.png b/msautotest/renderers/expected/rgb_overlay_res_to8bit.png index 751ca484b2..f067a7fef7 100644 Binary files a/msautotest/renderers/expected/rgb_overlay_res_to8bit.png and b/msautotest/renderers/expected/rgb_overlay_res_to8bit.png differ diff --git a/msautotest/renderers/expected/rgb_overlay_res_to8bit.svg b/msautotest/renderers/expected/rgb_overlay_res_to8bit.svg index 05570bafb7..9c2bef8544 100644 --- a/msautotest/renderers/expected/rgb_overlay_res_to8bit.svg +++ b/msautotest/renderers/expected/rgb_overlay_res_to8bit.svg @@ -2,7 +2,7 @@ - + diff --git a/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.cairo.png b/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.cairo.png index 751ca484b2..f067a7fef7 100644 Binary files a/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.cairo.png and b/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.cairo.png differ diff --git a/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.pdf b/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.pdf index 2641adef14..f4077469b6 100644 Binary files a/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.pdf and b/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.pdf differ diff --git a/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.png b/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.png index 751ca484b2..f067a7fef7 100644 Binary files a/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.png and b/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.png differ diff --git a/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.svg b/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.svg index 05570bafb7..9c2bef8544 100644 --- a/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.svg +++ b/msautotest/renderers/expected/rgb_overlay_res_to8bit_dithered.svg @@ -2,7 +2,7 @@ - + diff --git a/msautotest/renderers/expected/rgba_overlay_res.cairo.png b/msautotest/renderers/expected/rgba_overlay_res.cairo.png index 3b3d957a3b..4b4723824e 100644 Binary files a/msautotest/renderers/expected/rgba_overlay_res.cairo.png and b/msautotest/renderers/expected/rgba_overlay_res.cairo.png differ diff --git a/msautotest/renderers/expected/rgba_overlay_res.pdf b/msautotest/renderers/expected/rgba_overlay_res.pdf index e0fb9808a2..6f7ab98a05 100644 Binary files a/msautotest/renderers/expected/rgba_overlay_res.pdf and b/msautotest/renderers/expected/rgba_overlay_res.pdf differ diff --git a/msautotest/renderers/expected/rgba_overlay_res.png b/msautotest/renderers/expected/rgba_overlay_res.png index 3b3d957a3b..4b4723824e 100644 Binary files a/msautotest/renderers/expected/rgba_overlay_res.png and b/msautotest/renderers/expected/rgba_overlay_res.png differ diff --git a/msautotest/renderers/expected/rgba_overlay_res.svg b/msautotest/renderers/expected/rgba_overlay_res.svg index dc852c6189..3c63832f9a 100644 --- a/msautotest/renderers/expected/rgba_overlay_res.svg +++ b/msautotest/renderers/expected/rgba_overlay_res.svg @@ -2,7 +2,7 @@ - + diff --git a/msautotest/renderers/expected/uvraster.cairo.png b/msautotest/renderers/expected/uvraster.cairo.png index f905fed8f9..5366bacd8c 100644 Binary files a/msautotest/renderers/expected/uvraster.cairo.png and b/msautotest/renderers/expected/uvraster.cairo.png differ diff --git a/msautotest/renderers/expected/uvraster.pdf b/msautotest/renderers/expected/uvraster.pdf index b81a314a75..3406bc0571 100644 Binary files a/msautotest/renderers/expected/uvraster.pdf and b/msautotest/renderers/expected/uvraster.pdf differ diff --git a/msautotest/renderers/expected/uvraster.png b/msautotest/renderers/expected/uvraster.png index 2064acc489..bd56629f28 100644 Binary files a/msautotest/renderers/expected/uvraster.png and b/msautotest/renderers/expected/uvraster.png differ diff --git a/msautotest/renderers/expected/uvraster.svg b/msautotest/renderers/expected/uvraster.svg index bb7a0ec928..5d8b0c91fa 100644 --- a/msautotest/renderers/expected/uvraster.svg +++ b/msautotest/renderers/expected/uvraster.svg @@ -2,532 +2,532 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/msautotest/renderers/expected/uvraster_reproj.cairo.png b/msautotest/renderers/expected/uvraster_reproj.cairo.png index cd7f015266..c676acb70d 100644 Binary files a/msautotest/renderers/expected/uvraster_reproj.cairo.png and b/msautotest/renderers/expected/uvraster_reproj.cairo.png differ diff --git a/msautotest/renderers/expected/uvraster_reproj.pdf b/msautotest/renderers/expected/uvraster_reproj.pdf index 4db4f1f839..5ff9147f90 100644 Binary files a/msautotest/renderers/expected/uvraster_reproj.pdf and b/msautotest/renderers/expected/uvraster_reproj.pdf differ diff --git a/msautotest/renderers/expected/uvraster_reproj.png b/msautotest/renderers/expected/uvraster_reproj.png index a25f648e9e..7a622ca532 100644 Binary files a/msautotest/renderers/expected/uvraster_reproj.png and b/msautotest/renderers/expected/uvraster_reproj.png differ diff --git a/msautotest/renderers/expected/uvraster_reproj.svg b/msautotest/renderers/expected/uvraster_reproj.svg index 79e495b074..9c03cc63b9 100644 --- a/msautotest/renderers/expected/uvraster_reproj.svg +++ b/msautotest/renderers/expected/uvraster_reproj.svg @@ -2,489 +2,489 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/msautotest/renderers/legend_label_offset.map b/msautotest/renderers/legend_label_offset.map new file mode 100644 index 0000000000..5c7c921f57 --- /dev/null +++ b/msautotest/renderers/legend_label_offset.map @@ -0,0 +1,247 @@ +# RUN_PARMS: legend_label_offset.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&mode=legend&map.imagetype=png" > [RESULT_DEMIME] +# RUN_PARMS: legend_label_offset.cairo.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&mode=legend&map.imagetype=cairopng" > [RESULT_DEMIME] +# RUN_PARMS: legend_label_offset.svg [MAPSERV] QUERY_STRING="map=[MAPFILE]&mode=legend&map.imagetype=svg" > [RESULT_DEMIME] +# RUN_PARMS: legend_label_offset.pdf [MAPSERV] QUERY_STRING="map=[MAPFILE]&mode=legend&map.imagetype=pdf" > [RESULT_DEMIME] + +# +# +# legend support. +# +# REQUIRES: OUTPUT=PNG +# +MAP + +STATUS ON +EXTENT 478300 4762880 481650 4765610 +SIZE 150 100 +shapepath "../misc/data" +IMAGETYPE png +fontset "../misc/fonts.lst" +imagecolor 255 200 0 + +symbol + name "circle" + type ellipse + points 1 1 end + filled true +end + +LEGEND + imagecolor 255 255 255 + KEYSIZE 30 30 + KEYSPACING 5 3 + label + type truetype + color 0 0 0 + font "default" + size 9 + # added OFFSET to position the text in relation to the symbol + # -10 text should be shown some pixel up + # https://github.com/mapserver/mapserver/pull/5267 + OFFSET 0 -10 + end +END + +LAYER + NAME "points" + TYPE point + STATUS default + CLASS + NAME "point text+shape" + style + symbol "circle" + size 10 + color 255 0 0 + outlinecolor 0 0 0 + end + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + END + END + CLASS + NAME "point labelpnt+shape" + style + symbol "circle" + size 10 + color 255 0 0 + outlinecolor 0 0 0 + end + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + style + geomtransform "labelpnt" + symbol "circle" + size 5 + color 200 200 200 + outlinecolor 0 0 0 + end + END + END + CLASS + NAME "point labelpnt only" + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + style + geomtransform "labelpnt" + symbol "circle" + size 5 + color 200 200 200 + outlinecolor 0 0 0 + end + END + END + CLASS + NAME "point text only" + LABEL + type truetype + size 9 + color 255 255 255 + outlinecolor 0 0 0 + outlinewidth 1 + font "default" + END + END +END + +LAYER + NAME lines + TYPE line + STATUS default + CLASS + NAME "line text+shape" + COLOR 255 0 0 + OUTLINECOLOR 0 0 0 + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + END + END + CLASS + NAME "line labelpnt+shape" + COLOR 0 255 0 + OUTLINECOLOR 0 0 0 + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + style + geomtransform "labelpnt" + symbol "circle" + size 5 + color 200 200 200 + outlinecolor 0 0 0 + end + END + END + CLASS + NAME "line labelpnt only" + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + style + geomtransform "labelpnt" + symbol "circle" + size 5 + color 200 200 200 + outlinecolor 0 0 0 + end + END + END + CLASS + NAME "line text only" + LABEL + type truetype + size 9 + color 255 255 255 + outlinecolor 0 0 0 + outlinewidth 1 + font "default" + END + END + CLASS + NAME 'line with outline' + STYLE + color '#4186f0' + width 3 + outlinewidth 1 + outlinecolor '#000000' + END + END +END +LAYER + NAME shppoly + TYPE polygon + STATUS default + CLASS + NAME "poly text+shape" + COLOR 255 0 0 + OUTLINECOLOR 0 0 0 + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + END + END + CLASS + NAME "poly labelpnt+shape" + COLOR 0 255 0 + OUTLINECOLOR 0 0 0 + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + style + geomtransform "labelpnt" + symbol "circle" + size 5 + color 200 200 200 + outlinecolor 0 0 0 + end + END + END + CLASS + NAME "poly labelpnt only" + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + style + geomtransform "labelpnt" + symbol "circle" + size 5 + color 200 200 200 + outlinecolor 0 0 0 + end + END + END + CLASS + NAME "poly text only" + LABEL + type truetype + size 9 + color 255 255 255 + outlinecolor 0 0 0 + outlinewidth 1 + font "default" + END + END +END + +END diff --git a/msautotest/renderers/legend_raster_gradient.map b/msautotest/renderers/legend_raster_gradient.map new file mode 100644 index 0000000000..f84f282f76 --- /dev/null +++ b/msautotest/renderers/legend_raster_gradient.map @@ -0,0 +1,38 @@ +# RUN_PARMS: legend_raster_gradient.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&mode=legend&map.imagetype=png" > [RESULT_DEMIME] + +MAP + +NAME TEST +STATUS ON +SIZE 200 150 +EXTENT 0.5 0.5 399.5 299.5 +IMAGECOLOR 255 255 0 + +IMAGETYPE png24_t + +OUTPUTFORMAT + NAME png24_t + DRIVER "GDAL/PNG" + IMAGEMODE RGBA + TRANSPARENT ON +END + +LAYER + NAME rgb + TYPE raster + STATUS default + DATA ../gdal/data/rgba.tif + PROCESSING "BANDS=1,2,3" + + CLASS + NAME "" + EXPRESSION ([pixel] >= 0.01 AND [pixel] < 0.05) + STYLE + COLORRANGE 0 0 0 255 255 255 + DATARANGE 0.01 0.05 + END + END + +END + +END # of map file diff --git a/msautotest/renderers/legend_sizeunits_meters.map b/msautotest/renderers/legend_sizeunits_meters.map new file mode 100644 index 0000000000..7ce5f2ba04 --- /dev/null +++ b/msautotest/renderers/legend_sizeunits_meters.map @@ -0,0 +1,247 @@ +# RUN_PARMS: legend_sizeunits_meters.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&mode=legend&map.imagetype=png" > [RESULT_DEMIME] +# RUN_PARMS: legend_sizeunits_meters.cairo.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&mode=legend&map.imagetype=cairopng" > [RESULT_DEMIME] +# RUN_PARMS: legend_sizeunits_meters.svg [MAPSERV] QUERY_STRING="map=[MAPFILE]&mode=legend&map.imagetype=svg" > [RESULT_DEMIME] +# RUN_PARMS: legend_sizeunits_meters.pdf [MAPSERV] QUERY_STRING="map=[MAPFILE]&mode=legend&map.imagetype=pdf" > [RESULT_DEMIME] + +# +# +# legend support. +# +# REQUIRES: OUTPUT=PNG +# +MAP + +STATUS ON +EXTENT 478300 4762880 481650 4765610 +SIZE 150 100 +shapepath "../misc/data" +IMAGETYPE png +fontset "../misc/fonts.lst" +imagecolor 255 200 0 + +symbol + name "circle" + type ellipse + points 1 1 end + filled true +end + +LEGEND + imagecolor 255 255 255 + label + type truetype + color 0 0 0 + font "default" + size 9 + end +END + +LAYER + NAME "points" + TYPE point + STATUS default + + # Legend MapServer 7.0.1 Label SIZE is ignored when using SIZEUNITS meters + # Legend Label is very small + # https://github.com/mapserver/mapserver/pull/5268 + SIZEUNITS meters + + CLASS + NAME "point text+shape" + style + symbol "circle" + size 10 + color 255 0 0 + outlinecolor 0 0 0 + end + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + END + END + CLASS + NAME "point labelpnt+shape" + style + symbol "circle" + size 10 + color 255 0 0 + outlinecolor 0 0 0 + end + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + style + geomtransform "labelpnt" + symbol "circle" + size 5 + color 200 200 200 + outlinecolor 0 0 0 + end + END + END + CLASS + NAME "point labelpnt only" + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + style + geomtransform "labelpnt" + symbol "circle" + size 5 + color 200 200 200 + outlinecolor 0 0 0 + end + END + END + CLASS + NAME "point text only" + LABEL + type truetype + size 9 + color 255 255 255 + outlinecolor 0 0 0 + outlinewidth 1 + font "default" + END + END +END + +LAYER + NAME lines + TYPE line + STATUS default + CLASS + NAME "line text+shape" + COLOR 255 0 0 + OUTLINECOLOR 0 0 0 + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + END + END + CLASS + NAME "line labelpnt+shape" + COLOR 0 255 0 + OUTLINECOLOR 0 0 0 + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + style + geomtransform "labelpnt" + symbol "circle" + size 5 + color 200 200 200 + outlinecolor 0 0 0 + end + END + END + CLASS + NAME "line labelpnt only" + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + style + geomtransform "labelpnt" + symbol "circle" + size 5 + color 200 200 200 + outlinecolor 0 0 0 + end + END + END + CLASS + NAME "line text only" + LABEL + type truetype + size 9 + color 255 255 255 + outlinecolor 0 0 0 + outlinewidth 1 + font "default" + END + END + CLASS + NAME 'line with outline' + STYLE + color '#4186f0' + width 3 + outlinewidth 1 + outlinecolor '#000000' + END + END +END +LAYER + NAME shppoly + TYPE polygon + STATUS default + CLASS + NAME "poly text+shape" + COLOR 255 0 0 + OUTLINECOLOR 0 0 0 + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + END + END + CLASS + NAME "poly labelpnt+shape" + COLOR 0 255 0 + OUTLINECOLOR 0 0 0 + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + style + geomtransform "labelpnt" + symbol "circle" + size 5 + color 200 200 200 + outlinecolor 0 0 0 + end + END + END + CLASS + NAME "poly labelpnt only" + LABEL + type truetype + size 9 + color 0 0 0 + font "default" + style + geomtransform "labelpnt" + symbol "circle" + size 5 + color 200 200 200 + outlinecolor 0 0 0 + end + END + END + CLASS + NAME "poly text only" + LABEL + type truetype + size 9 + color 255 255 255 + outlinecolor 0 0 0 + outlinewidth 1 + font "default" + END + END +END + +END diff --git a/msautotest/renderers/multilabel-leader.map b/msautotest/renderers/multilabel-leader.map new file mode 100644 index 0000000000..2d24a22b49 --- /dev/null +++ b/msautotest/renderers/multilabel-leader.map @@ -0,0 +1,573 @@ +# RUN_PARMS: multilabel-leader.png [SHP2IMG] -m [MAPFILE] -i png -o [RESULT] +# RUN_PARMS: multilabel-leader.pdf [SHP2IMG] -m [MAPFILE] -i pdf -o [RESULT] +# RUN_PARMS: multilabel-leader.svg [SHP2IMG] -m [MAPFILE] -i svg -o [RESULT] +# RUN_PARMS: multilabel-leader.cairo.png [SHP2IMG] -m [MAPFILE] -i cairopng -o [RESULT] +# +map + +imagetype png +size 400 300 +extent -85 -40 10 30 +web + metadata + "ows_enable_request" "*" + "ows_srs" "EPSG:4326" + "labelcache_map_edge_buffer" "10" + end +end + + +#debug 10 +#config "MS_ERRORFILE" "stderr" +projection + "init=epsg:4326" +end +imagecolor 230 230 230 +fontset "data/fonts.lst" + +symbol + type ellipse + points 1 1 end + name "circle" + filled true +end + symbol + name "v10" + type truetype + font "dejavu" + character "➜" + anchorpoint 0.30 0.85 + end + symbol + name "v20" + type truetype + font "dejavu" + character "➝" + anchorpoint 0.30 0.85 + end + symbol + name "v30" + type truetype + font "dejavu" + character "➞" + anchorpoint 0.30 0.85 + end + symbol + name "v40" + type truetype + font "dejavu" + character "➟" + anchorpoint 0.30 0.85 + end + symbol + name "v50" + type truetype + font "dejavu" + character "➠" + anchorpoint 0.30 0.85 + end + symbol + name "v60" + type truetype + font "dejavu" + character "➡" + anchorpoint 0.30 0.85 + end + symbol + name "v70" + type truetype + font "dejavu" + character "➢" + anchorpoint 0.30 0.85 + end + symbol + name "v80" + type truetype + font "dejavu" + character "➣" + anchorpoint 0.30 0.85 + end + symbol + name "v90" + type truetype + font "dejavu" + character "➤" + anchorpoint 0.30 0.85 + end + symbol + name "v100" + type truetype + font "dejavu" + character "➥" + anchorpoint 0.30 0.85 + end + symbol + name "v110" + type truetype + font "dejavu" + character "➦" + anchorpoint 0.30 0.85 + end + symbol + name "v120" + type truetype + font "dejavu" + character "➧" + anchorpoint 0.30 0.85 + end + symbol + name "v130" + type truetype + font "dejavu" + character "➨" + anchorpoint 0.30 0.85 + end + symbol + name "v140" + type truetype + font "dejavu" + character "➩" + anchorpoint 0.30 0.85 + end + symbol + name "n0" + type truetype + font "dejavu" + character "⚐" + end + symbol + name "n1" + type truetype + font "dejavu" + character "⚑" + end + symbol + name "n2" + type truetype + font "dejavu" + character "⚒" + end + symbol + name "n3" + type truetype + font "dejavu" + character "⚓" + end + symbol + name "n4" + type truetype + font "dejavu" + character "⚔" + end + symbol + name "n5" + type truetype + font "dejavu" + character "⚕" + end + symbol + name "n6" + type truetype + font "dejavu" + character "⚖" + end + symbol + name "n7" + type truetype + font "dejavu" + character "⚗" + end + symbol + name "n8" + type truetype + font "dejavu" + character "⚘" + end + symbol + name "n9" + type truetype + font "dejavu" + character "⚙" + end + +layer + type point + status on + name "p2" + group "p1" + data "data/meteo.shp" + class + style + symbol "circle" + outlinecolor 255 0 0 + size 2 + end + end +end + +layer + type point + status on + name "met" + group "p1" + data "data/meteo.shp" + class + leader + maxdistance 50 + gridstep 10 + style + color 255 0 0 + width 4 + end + end + label + partials false + force group + style + geomtransform labelpnt + symbol "circle" + opacity 30 + color 200 200 200 + outlinecolor 0 0 0 + size 60 + end + end + + label + partials false + text "[p]" + font "dejavu" + size 7 + type truetype + color 0 0 0 + offset 12 -12 + force group + end + label + expression ([dp]>=0) + text "+[dp]" + font "dejavu" + size 7 + type truetype + color 0 0 0 + offset 12 0 + force group + end + label + expression ([dp]<0) + text "[dp]" + font "dejavu" + size 7 + type truetype + color 0 0 0 + offset 12 0 + force group + end + label + expression ([wspeed] > 0 and [wspeed] <= 10) + style + color 0 0 0 + geomtransform labelpnt + angle [wangle] + symbol "v10" + size 15 + end + + force group + end + label + expression ([wspeed] > 10 and [wspeed] <= 20) + style + color 0 0 0 + geomtransform labelpnt + angle [wangle] + symbol "v20" + size 15 + end + + force group + end + label + expression ([wspeed] > 20 and [wspeed] <= 30) + style + color 0 0 0 + geomtransform labelpnt + angle [wangle] + symbol "v30" + size 15 + end + + force group + end + label + expression ([wspeed] > 30 and [wspeed] <= 40) + style + color 0 0 0 + geomtransform labelpnt + angle [wangle] + symbol "v40" + size 15 + end + + force group + end + label + expression ([wspeed] > 40 and [wspeed] <= 50) + style + color 0 0 0 + geomtransform labelpnt + angle [wangle] + symbol "v50" + size 15 + end + + force group + end + label + expression ([wspeed] > 50 and [wspeed] <= 60) + style + color 0 0 0 + geomtransform labelpnt + angle [wangle] + symbol "v60" + size 15 + end + + force group + end + label + expression ([wspeed] > 60 and [wspeed] <= 70) + style + color 0 0 0 + geomtransform labelpnt + angle [wangle] + symbol "v70" + size 15 + end + + force group + end + label + expression ([wspeed] > 70 and [wspeed] <= 80) + style + color 0 0 0 + geomtransform labelpnt + angle [wangle] + symbol "v80" + size 15 + end + + force group + end + label + expression ([wspeed] > 80 and [wspeed] <= 90) + style + color 0 0 0 + geomtransform labelpnt + angle [wangle] + symbol "v90" + size 15 + end + + force group + end + label + expression ([wspeed] > 90 and [wspeed] <= 100) + style + color 0 0 0 + geomtransform labelpnt + angle [wangle] + symbol "v100" + size 15 + end + + force group + end + label + expression ([wspeed] > 100 and [wspeed] <= 110) + style + color 0 0 0 + geomtransform labelpnt + angle [wangle] + symbol "v110" + size 15 + end + + force group + end + label + expression ([wspeed] > 110 and [wspeed] <= 120) + style + color 0 0 0 + geomtransform labelpnt + angle [wangle] + symbol "v120" + size 15 + end + + force group + end + label + expression ([wspeed] > 120 and [wspeed] <= 130) + style + color 0 0 0 + geomtransform labelpnt + angle [wangle] + symbol "v130" + size 15 + end + + force group + end + label + expression ([wspeed] > 130 and [wspeed] <= 140) + style + color 0 0 0 + geomtransform labelpnt + angle [wangle] + symbol "v140" + size 15 + end + + force group + end + label + expression ([nebul]=0) + style + geomtransform labelpnt + color 0 0 0 + symbol "n0" + size 10 + offset -12 0 + end + force group + end + label + expression ([nebul]=1) + style + geomtransform labelpnt + color 0 0 0 + symbol "n1" + size 10 + offset -12 0 + end + force group + end + label + expression ([nebul]=2) + style + geomtransform labelpnt + color 0 0 0 + symbol "n2" + size 10 + offset -12 0 + end + force group + end + label + expression ([nebul]=3) + style + geomtransform labelpnt + color 0 0 0 + symbol "n3" + size 10 + offset -12 0 + end + force group + end + label + expression ([nebul]=4) + style + geomtransform labelpnt + color 0 0 0 + symbol "n4" + size 10 + offset -12 0 + end + force group + end + label + expression ([nebul]=5) + style + geomtransform labelpnt + color 0 0 0 + symbol "n5" + size 10 + offset -12 0 + end + force group + end + label + expression ([nebul]=6) + style + geomtransform labelpnt + color 0 0 0 + symbol "n6" + size 10 + offset -12 0 + end + force group + end + label + expression ([nebul]=7) + style + geomtransform labelpnt + color 0 0 0 + symbol "n7" + size 10 + offset -12 0 + end + force group + end + label + expression ([nebul]=8) + style + geomtransform labelpnt + color 0 0 0 + symbol "n8" + size 10 + offset -12 0 + end + force group + end + label + expression ([nebul]=9) + style + geomtransform labelpnt + color 0 0 0 + symbol "n9" + size 10 + offset -12 0 + end + force group + end + + label + expression ([temp]<0) + text "-[temp]" + type truetype + font "dejavu" + size 7 + offset -12 -12 + color 0 0 0 + force group + end + label + expression ([temp]>=0) + text "+[temp]" + type truetype + font "dejavu" + size 7 + offset -12 -12 + color 0 0 0 + force group + style + geomtransform labelpoly + outlinecolor 255 0 0 + width 1 + end + end + end +end + +end diff --git a/msautotest/valgrind-suppressions.txt b/msautotest/valgrind-suppressions.txt index f06dcb92ed..f268589918 100644 --- a/msautotest/valgrind-suppressions.txt +++ b/msautotest/valgrind-suppressions.txt @@ -93,3 +93,131 @@ fun:pixman_constructor ... } + +{ + + Memcheck:Free + fun:free + obj:/lib/libc-2.11.1.so + obj:/lib/libc-2.11.1.so + fun:_vgnU_freeres + fun:exit + fun:main +} + +{ + + Memcheck:Leak + ... + fun:H5P_init + ... +} + +{ + + Memcheck:Leak + ... + fun:H5D_init + ... +} + +{ + + Memcheck:Leak + ... + fun:H5E_init + ... +} + +{ + + Memcheck:Leak + ... + fun:H5T_init + ... +} + +{ + + Memcheck:Leak + ... + fun:H5L_init + ... +} + +{ + + Memcheck:Leak + fun:malloc + ... + fun:H5FL_reg_malloc + fun:H5E_get_stack + fun:H5E_clear_stack + fun:H5Tcopy + ... +} + +{ + + Memcheck:Leak + fun:calloc + fun:H5TS_cancel_count_inc + fun:H5open + ... +} + + +{ + + Memcheck:Leak + fun:malloc + fun:gmalloc + fun:copyString + fun:_ZN6Object8initNameEPKc + fun:_GLOBAL__I_StructElement.cc +} + +{ + + Memcheck:Leak + fun:malloc + ... + fun:_ZN5mongo3TSPINS_18OwnedPointerVectorISt19basic_ostringstreamIcSt11char_traitsIcESaIcEEEEED1Ev + fun:__cxa_finalize + ... +} + +{ + + Memcheck:Leak + fun:_Znwm + fun:_GLOBAL__I_message_port.cpp + ... +} + +{ + + Memcheck:Leak + ... + fun:_ZN4geos4geom15GeometryFactoryC1Ev + fun:_Z41__static_initialization_and_destruction_0ii + fun:_GLOBAL__I_GeometryFactory.cpp + ... +} + +{ + + Memcheck:Leak + fun:_Znwm + fun:_Z41__static_initialization_and_destruction_0ii + fun:_GLOBAL__I_GeometryFactory.cpp + ... +} + +{ + + Memcheck:Leak + fun:malloc + fun:OS_LibInit + ... +} diff --git a/msautotest/wxs/data/db.sqlite b/msautotest/wxs/data/db.sqlite new file mode 100644 index 0000000000..cf763a153e Binary files /dev/null and b/msautotest/wxs/data/db.sqlite differ diff --git a/msautotest/wxs/data/point_2_49.dbf b/msautotest/wxs/data/point_2_49.dbf new file mode 100644 index 0000000000..8d68941a5c Binary files /dev/null and b/msautotest/wxs/data/point_2_49.dbf differ diff --git a/msautotest/wxs/data/point_2_49.shp b/msautotest/wxs/data/point_2_49.shp new file mode 100644 index 0000000000..3ba5f0caa0 Binary files /dev/null and b/msautotest/wxs/data/point_2_49.shp differ diff --git a/msautotest/wxs/data/point_2_49.shx b/msautotest/wxs/data/point_2_49.shx new file mode 100644 index 0000000000..3416da7c30 Binary files /dev/null and b/msautotest/wxs/data/point_2_49.shx differ diff --git a/msautotest/wxs/data/point_3_50.dbf b/msautotest/wxs/data/point_3_50.dbf new file mode 100644 index 0000000000..89c0aa0285 Binary files /dev/null and b/msautotest/wxs/data/point_3_50.dbf differ diff --git a/msautotest/wxs/data/point_3_50.shp b/msautotest/wxs/data/point_3_50.shp new file mode 100644 index 0000000000..6a495ee532 Binary files /dev/null and b/msautotest/wxs/data/point_3_50.shp differ diff --git a/msautotest/wxs/data/point_3_50.shx b/msautotest/wxs/data/point_3_50.shx new file mode 100644 index 0000000000..25b9aae828 Binary files /dev/null and b/msautotest/wxs/data/point_3_50.shx differ diff --git a/msautotest/wxs/data/polar_stereo.tif b/msautotest/wxs/data/polar_stereo.tif new file mode 100644 index 0000000000..db3599c177 Binary files /dev/null and b/msautotest/wxs/data/polar_stereo.tif differ diff --git a/msautotest/wxs/data/shp_tileindex_of_shp.dbf b/msautotest/wxs/data/shp_tileindex_of_shp.dbf new file mode 100644 index 0000000000..bc18a8e3b7 Binary files /dev/null and b/msautotest/wxs/data/shp_tileindex_of_shp.dbf differ diff --git a/msautotest/wxs/data/shp_tileindex_of_shp.shp b/msautotest/wxs/data/shp_tileindex_of_shp.shp new file mode 100644 index 0000000000..013fd95aba Binary files /dev/null and b/msautotest/wxs/data/shp_tileindex_of_shp.shp differ diff --git a/msautotest/wxs/data/shp_tileindex_of_shp.shx b/msautotest/wxs/data/shp_tileindex_of_shp.shx new file mode 100644 index 0000000000..3949bc20a9 Binary files /dev/null and b/msautotest/wxs/data/shp_tileindex_of_shp.shx differ diff --git a/msautotest/wxs/data/test5299.csv b/msautotest/wxs/data/test5299.csv new file mode 100644 index 0000000000..70daad4243 --- /dev/null +++ b/msautotest/wxs/data/test5299.csv @@ -0,0 +1,2 @@ +id,WKT +1,"MULTIPOLYGON(((676881.746 253159.65,676952.5 253142.812,676984.539 253076.568,676992.16 253047.552,676907.575 252978.182,676793.971 252977.057,676763.746 253101.446,676881.746 253159.65),(676881.746 253159.65,676835.762 253108.566,676841.704 253079.649,676870.271 253078.765,676924.143 253120.438,676881.746 253159.65)))" diff --git a/msautotest/wxs/data/ticket5445.tif b/msautotest/wxs/data/ticket5445.tif new file mode 100644 index 0000000000..33cfa58cea Binary files /dev/null and b/msautotest/wxs/data/ticket5445.tif differ diff --git a/msautotest/wxs/data/uvraster_lonwrap180.tif b/msautotest/wxs/data/uvraster_lonwrap180.tif new file mode 100644 index 0000000000..5e47c9891b Binary files /dev/null and b/msautotest/wxs/data/uvraster_lonwrap180.tif differ diff --git a/msautotest/wxs/data/wms_uvraster_map_reprojection.tif b/msautotest/wxs/data/wms_uvraster_map_reprojection.tif new file mode 100644 index 0000000000..a6fcd941c3 Binary files /dev/null and b/msautotest/wxs/data/wms_uvraster_map_reprojection.tif differ diff --git a/msautotest/wxs/expected/ows_all_wms_capabilities.xml b/msautotest/wxs/expected/ows_all_wms_capabilities.xml index b47eaa53a6..f3bced180f 100644 --- a/msautotest/wxs/expected/ows_all_wms_capabilities.xml +++ b/msautotest/wxs/expected/ows_all_wms_capabilities.xml @@ -35,8 +35,8 @@ Content-Type: text/xml; charset=UTF-8 none none - 2048 - 2048 + 4096 + 4096 @@ -59,6 +59,7 @@ Content-Type: text/xml; charset=UTF-8 image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/ows_all_wms_capabilities_post.xml b/msautotest/wxs/expected/ows_all_wms_capabilities_post.xml index b47eaa53a6..f3bced180f 100644 --- a/msautotest/wxs/expected/ows_all_wms_capabilities_post.xml +++ b/msautotest/wxs/expected/ows_all_wms_capabilities_post.xml @@ -35,8 +35,8 @@ Content-Type: text/xml; charset=UTF-8 none none - 2048 - 2048 + 4096 + 4096 @@ -59,6 +59,7 @@ Content-Type: text/xml; charset=UTF-8 image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/ows_wms_capabilities.xml b/msautotest/wxs/expected/ows_wms_capabilities.xml index 94f19ea695..260ceb071d 100644 --- a/msautotest/wxs/expected/ows_wms_capabilities.xml +++ b/msautotest/wxs/expected/ows_wms_capabilities.xml @@ -10,8 +10,8 @@ Content-Type: text/xml; charset=UTF-8 - 2048 - 2048 + 4096 + 4096 @@ -34,6 +34,7 @@ Content-Type: text/xml; charset=UTF-8 image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wcs11_post_getcov_gdpng8.dat b/msautotest/wxs/expected/wcs11_post_getcov_gdpng8.dat index f07fa5820a..2655644e89 100644 Binary files a/msautotest/wxs/expected/wcs11_post_getcov_gdpng8.dat and b/msautotest/wxs/expected/wcs11_post_getcov_gdpng8.dat differ diff --git a/msautotest/wxs/expected/wcs11_post_getcov_grd_4326.dat b/msautotest/wxs/expected/wcs11_post_getcov_grd_4326.dat index b889fb2b99..6222115cd5 100644 --- a/msautotest/wxs/expected/wcs11_post_getcov_grd_4326.dat +++ b/msautotest/wxs/expected/wcs11_post_getcov_grd_4326.dat @@ -39,7 +39,7 @@ NODATA_value -99 -99 165 181 115 90 132 107 123 197 230 197 148 -99 255 222 255 123 140 123 140 173 214 148 173 -99 206 255 255 132 156 140 99 132 165 197 165 - -99 -99 -99 -99 -99 -99 -99 -99 -99 -99 -99 -99 + -99 255 255 140 140 148 156 148 148 132 140 214 --wcs Content-Type: application/octet-stream diff --git a/msautotest/wxs/expected/wcs11_post_getcov_grd_wgs84.dat b/msautotest/wxs/expected/wcs11_post_getcov_grd_wgs84.dat index b889fb2b99..6222115cd5 100644 --- a/msautotest/wxs/expected/wcs11_post_getcov_grd_wgs84.dat +++ b/msautotest/wxs/expected/wcs11_post_getcov_grd_wgs84.dat @@ -39,7 +39,7 @@ NODATA_value -99 -99 165 181 115 90 132 107 123 197 230 197 148 -99 255 222 255 123 140 123 140 173 214 148 173 -99 206 255 255 132 156 140 99 132 165 197 165 - -99 -99 -99 -99 -99 -99 -99 -99 -99 -99 -99 -99 + -99 255 255 140 140 148 156 148 148 132 140 214 --wcs Content-Type: application/octet-stream diff --git a/msautotest/wxs/expected/wcs_10_getcov_bands_name_new.dat b/msautotest/wxs/expected/wcs_10_getcov_bands_name_new.dat index 61a19d9fe3..5cbaa11c3e 100644 Binary files a/msautotest/wxs/expected/wcs_10_getcov_bands_name_new.dat and b/msautotest/wxs/expected/wcs_10_getcov_bands_name_new.dat differ diff --git a/msautotest/wxs/expected/wcs_20_desc.txt b/msautotest/wxs/expected/wcs_20_desc.txt index 86657fdd9b..a6807df945 100644 --- a/msautotest/wxs/expected/wcs_20_desc.txt +++ b/msautotest/wxs/expected/wcs_20_desc.txt @@ -21,7 +21,7 @@ Content-Type: text/xml; charset=UTF-8 x y - 0.000000 300.000000 + 5.000000 295.000000 10.000000 0 @@ -30,7 +30,7 @@ Content-Type: text/xml; charset=UTF-8 - + Test description diff --git a/msautotest/wxs/expected/wcs_20_desc.xml b/msautotest/wxs/expected/wcs_20_desc.xml index 20bc0d133b..cc10682955 100644 --- a/msautotest/wxs/expected/wcs_20_desc.xml +++ b/msautotest/wxs/expected/wcs_20_desc.xml @@ -19,7 +19,7 @@ x y - 0.000000 300.000000 + 5.000000 295.000000 10.000000 0 @@ -28,7 +28,7 @@ - + Test description diff --git a/msautotest/wxs/expected/wcs_20_desc_bands.xml b/msautotest/wxs/expected/wcs_20_desc_bands.xml index bd08d5cdfc..cd29e475a7 100644 --- a/msautotest/wxs/expected/wcs_20_desc_bands.xml +++ b/msautotest/wxs/expected/wcs_20_desc_bands.xml @@ -16,10 +16,10 @@ 104 60 - lat long + long lat - 49.891143 14.470271 + 49.874157 14.487132 0 0.033722 @@ -204,10 +204,10 @@ 104 60 - lat long + long lat - 49.891143 14.470271 + 49.874157 14.487132 0 0.033722 @@ -352,7 +352,7 @@ - + Default description diff --git a/msautotest/wxs/expected/wcs_20_getcov_bands_name.dat b/msautotest/wxs/expected/wcs_20_getcov_bands_name.dat index c3bf3a5765..e21adb9098 100644 Binary files a/msautotest/wxs/expected/wcs_20_getcov_bands_name.dat and b/msautotest/wxs/expected/wcs_20_getcov_bands_name.dat differ diff --git a/msautotest/wxs/expected/wcs_20_getcov_bands_name_new.dat b/msautotest/wxs/expected/wcs_20_getcov_bands_name_new.dat index 5eeb68cb58..fa9862930b 100644 Binary files a/msautotest/wxs/expected/wcs_20_getcov_bands_name_new.dat and b/msautotest/wxs/expected/wcs_20_getcov_bands_name_new.dat differ diff --git a/msautotest/wxs/expected/wcs_20_getcov_bands_name_new_reproject.dat b/msautotest/wxs/expected/wcs_20_getcov_bands_name_new_reproject.dat index 5b5379baa8..73d2ac5a87 100644 Binary files a/msautotest/wxs/expected/wcs_20_getcov_bands_name_new_reproject.dat and b/msautotest/wxs/expected/wcs_20_getcov_bands_name_new_reproject.dat differ diff --git a/msautotest/wxs/expected/wcs_20_getcov_bands_single.tif b/msautotest/wxs/expected/wcs_20_getcov_bands_single.tif new file mode 100644 index 0000000000..ef5aedc821 Binary files /dev/null and b/msautotest/wxs/expected/wcs_20_getcov_bands_single.tif differ diff --git a/msautotest/wxs/expected/wcs_20_getcov_full.dat b/msautotest/wxs/expected/wcs_20_getcov_full.dat index 8c19d79bad..54cbeb80e2 100644 Binary files a/msautotest/wxs/expected/wcs_20_getcov_full.dat and b/msautotest/wxs/expected/wcs_20_getcov_full.dat differ diff --git a/msautotest/wxs/expected/wcs_20_getcov_grd_mp.dat b/msautotest/wxs/expected/wcs_20_getcov_grd_mp.dat index c9b662e61d..6b5201e438 100644 --- a/msautotest/wxs/expected/wcs_20_getcov_grd_mp.dat +++ b/msautotest/wxs/expected/wcs_20_getcov_grd_mp.dat @@ -23,7 +23,7 @@ Content-Type: application/gml+xml; charset=UTF-8 x y - 0.000000 300.000000 + 5.000000 295.000000 10.000000 0 @@ -40,7 +40,7 @@ Content-Type: application/gml+xml; charset=UTF-8 - + Test description diff --git a/msautotest/wxs/expected/wcs_20_getcov_reproj.dat b/msautotest/wxs/expected/wcs_20_getcov_reproj.dat index 6eb89c2e74..5f89408dd5 100644 Binary files a/msautotest/wxs/expected/wcs_20_getcov_reproj.dat and b/msautotest/wxs/expected/wcs_20_getcov_reproj.dat differ diff --git a/msautotest/wxs/expected/wcs_20_post_bands_name.dat b/msautotest/wxs/expected/wcs_20_post_bands_name.dat index c3bf3a5765..e21adb9098 100644 Binary files a/msautotest/wxs/expected/wcs_20_post_bands_name.dat and b/msautotest/wxs/expected/wcs_20_post_bands_name.dat differ diff --git a/msautotest/wxs/expected/wcs_20_post_bands_name_new.dat b/msautotest/wxs/expected/wcs_20_post_bands_name_new.dat index 5eeb68cb58..fa9862930b 100644 Binary files a/msautotest/wxs/expected/wcs_20_post_bands_name_new.dat and b/msautotest/wxs/expected/wcs_20_post_bands_name_new.dat differ diff --git a/msautotest/wxs/expected/wcs_20_post_desc.xml b/msautotest/wxs/expected/wcs_20_post_desc.xml index 796e7d7a98..6d3a863f94 100644 --- a/msautotest/wxs/expected/wcs_20_post_desc.xml +++ b/msautotest/wxs/expected/wcs_20_post_desc.xml @@ -19,7 +19,7 @@ x y - 0.000000 300.000000 + 5.000000 295.000000 10.000000 0 @@ -28,7 +28,7 @@ - + Test description diff --git a/msautotest/wxs/expected/wcs_20_post_getcov_full_multipart.dat b/msautotest/wxs/expected/wcs_20_post_getcov_full_multipart.dat index 5de0d5c258..276c3f88fd 100644 Binary files a/msautotest/wxs/expected/wcs_20_post_getcov_full_multipart.dat and b/msautotest/wxs/expected/wcs_20_post_getcov_full_multipart.dat differ diff --git a/msautotest/wxs/expected/wcs_getcov_grd_11_4326.dat b/msautotest/wxs/expected/wcs_getcov_grd_11_4326.dat index 10996c08ca..f568836dc7 100644 --- a/msautotest/wxs/expected/wcs_getcov_grd_11_4326.dat +++ b/msautotest/wxs/expected/wcs_getcov_grd_11_4326.dat @@ -39,7 +39,7 @@ NODATA_value -99 -99 165 181 115 90 132 107 123 197 230 197 148 -99 255 222 255 123 140 123 140 173 214 148 173 -99 206 255 255 132 156 140 99 132 165 197 165 - -99 -99 -99 -99 -99 -99 -99 -99 -99 -99 -99 -99 + -99 255 255 140 140 148 156 148 148 132 140 214 --wcs Content-Type: application/octet-stream diff --git a/msautotest/wxs/expected/wcs_getcov_grd_11_wgs84.dat b/msautotest/wxs/expected/wcs_getcov_grd_11_wgs84.dat index 10996c08ca..f568836dc7 100644 --- a/msautotest/wxs/expected/wcs_getcov_grd_11_wgs84.dat +++ b/msautotest/wxs/expected/wcs_getcov_grd_11_wgs84.dat @@ -39,7 +39,7 @@ NODATA_value -99 -99 165 181 115 90 132 107 123 197 230 197 148 -99 255 222 255 123 140 123 140 173 214 148 173 -99 206 255 255 132 156 140 99 132 165 197 165 - -99 -99 -99 -99 -99 -99 -99 -99 -99 -99 -99 -99 + -99 255 255 140 140 148 156 148 148 132 140 214 --wcs Content-Type: application/octet-stream diff --git a/msautotest/wxs/expected/wcs_getcov_png8_11.dat b/msautotest/wxs/expected/wcs_getcov_png8_11.dat index f07fa5820a..2655644e89 100644 Binary files a/msautotest/wxs/expected/wcs_getcov_png8_11.dat and b/msautotest/wxs/expected/wcs_getcov_png8_11.dat differ diff --git a/msautotest/wxs/expected/wcs_mask_20_getcov_full.dat b/msautotest/wxs/expected/wcs_mask_20_getcov_full.dat index 10196dde27..92a1214152 100644 Binary files a/msautotest/wxs/expected/wcs_mask_20_getcov_full.dat and b/msautotest/wxs/expected/wcs_mask_20_getcov_full.dat differ diff --git a/msautotest/wxs/expected/wcs_mask_20_getcov_grd_mp.dat b/msautotest/wxs/expected/wcs_mask_20_getcov_grd_mp.dat index 4eb914a254..d85effa762 100644 --- a/msautotest/wxs/expected/wcs_mask_20_getcov_grd_mp.dat +++ b/msautotest/wxs/expected/wcs_mask_20_getcov_grd_mp.dat @@ -23,7 +23,7 @@ Content-Type: application/gml+xml; charset=UTF-8 x y - 0.000000 300.000000 + 5.000000 295.000000 10.000000 0 @@ -40,7 +40,7 @@ Content-Type: application/gml+xml; charset=UTF-8 - + Test description diff --git a/msautotest/wxs/expected/wcs_mask_20_getcov_reproj.dat b/msautotest/wxs/expected/wcs_mask_20_getcov_reproj.dat index 563a404c14..97ea6d7863 100644 Binary files a/msautotest/wxs/expected/wcs_mask_20_getcov_reproj.dat and b/msautotest/wxs/expected/wcs_mask_20_getcov_reproj.dat differ diff --git a/msautotest/wxs/expected/wfs10_test_xml_escaping.xml b/msautotest/wxs/expected/wfs10_test_xml_escaping.xml new file mode 100644 index 0000000000..85554c0fa7 --- /dev/null +++ b/msautotest/wxs/expected/wfs10_test_xml_escaping.xml @@ -0,0 +1,108 @@ + + + + + MapServer WFS + title & title + abstract&abstract + + keyword&keyword + + http://localhost + fees&fees + accessconstraints&accessconstraints + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + province + title&title + abstract&abstract + EPSG:4326 + + http://path/to/metadata_url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/msautotest/wxs/expected/wfs11_test_xml_escaping.xml b/msautotest/wxs/expected/wfs11_test_xml_escaping.xml new file mode 100644 index 0000000000..5cac9ba558 --- /dev/null +++ b/msautotest/wxs/expected/wfs11_test_xml_escaping.xml @@ -0,0 +1,148 @@ + + + + title & title + abstract&abstract + + keyword&keyword + + OGC WFS + 1.1.0 + fees&fees + accessconstraints&accessconstraints + + + contactorganization&contactorganization + + + contactperson&contactperson + contactposition&contactposition + + + contactvoicetelephone&contactvoicetelephone + contactfacsimiletelephone&contactfacsimiletelephone + + + address&address + city&city + stateorprovince&stateorprovince + postcode&postcode + country&country + contactelectronicmailaddress&contactelectronicmailaddress + + + hoursofservice&_hoursofservice + contactinstructions&contactinstructions + + role&role + + + + + + + + + + + + WFS + + + 1.0.0 + 1.1.0 + + + text/xml + + + + + + + + + + + XMLSCHEMA + text/xml; subtype=gml/2.1.2 + text/xml; subtype=gml/3.1.1 + + + + + + + + + + + results + hits + + + text/xml; subtype=gml/3.1.1 + + + + + + Query + + + province + title&title + abstract&abstract + urn:ogc:def:crs:EPSG::4326 + urn:ogc:def:crs:EPSG::4269 + + text/xml; subtype=gml/3.1.1 + + + -66.724329085098 41.770507630784 + -57.721680231574 48.477313848494 + + http://path/to/metadata_url + + + + + + gml:Point + gml:LineString + gml:Polygon + gml:Envelope + + + + + + + + + + + + + + + + + + + LessThan + GreaterThan + LessThanEqualTo + GreaterThanEqualTo + EqualTo + NotEqualTo + Like + Between + + + + + + + + diff --git a/msautotest/wxs/expected/wfs20_test_xml_escaping.xml b/msautotest/wxs/expected/wfs20_test_xml_escaping.xml new file mode 100644 index 0000000000..b9fb3fc32a --- /dev/null +++ b/msautotest/wxs/expected/wfs20_test_xml_escaping.xml @@ -0,0 +1,346 @@ + + + + title & title + abstract&abstract + + keyword&keyword + + WFS + 2.0.0 + fees&fees + accessconstraints&accessconstraints + + + contactorganization&contactorganization + + + contactperson&contactperson + contactposition&contactposition + + + contactvoicetelephone&contactvoicetelephone + contactfacsimiletelephone&contactfacsimiletelephone + + + address&address + city&city + stateorprovince&stateorprovince + postcode&postcode + country&country + contactelectronicmailaddress&contactelectronicmailaddress + + + hoursofservice&_hoursofservice + contactinstructions&contactinstructions + + role&role + + + + + + + + + + + + + 2.0.0 + 1.1.0 + 1.0.0 + + + + + text/xml + + + + + ServiceIdentification + ServiceProvider + OperationsMetadata + FeatureTypeList + Filter_Capabilities + + + + + + + + + + + + + application/gml+xml; version=3.2 + text/xml; subtype=gml/3.2.1 + text/xml; subtype=gml/3.1.1 + text/xml; subtype=gml/2.1.2 + + + + + + + + + + + + + application/gml+xml; version=3.2 + text/xml; subtype=gml/3.2.1 + text/xml; subtype=gml/3.1.1 + text/xml; subtype=gml/2.1.2 + + + + + + + + + + + + + application/gml+xml; version=3.2 + text/xml; subtype=gml/3.2.1 + text/xml; subtype=gml/3.1.1 + text/xml; subtype=gml/2.1.2 + + + + + + + + + + + + + + + + + + + + + + 2.0.0 + 1.1.0 + 1.0.0 + + + + + TRUE + + + + FALSE + + + + FALSE + + + + TRUE + + + + TRUE + + + + FALSE + + + + FALSE + + + + FALSE + + + + TRUE + + + + FALSE + + + + FALSE + + + + FALSE + + + + FALSE + + + + FALSE + + + + FALSE + + + + wfs:Query + wfs:StoredQuery + + + + + + ms:province + title&title + abstract&abstract + urn:ogc:def:crs:EPSG::4326 + urn:ogc:def:crs:EPSG::4269 + + application/gml+xml; version=3.2 + text/xml; subtype=gml/3.2.1 + text/xml; subtype=gml/3.1.1 + text/xml; subtype=gml/2.1.2 + + + -66.724329085098 41.770507630784 + -57.721680231574 48.477313848494 + + + + + + + + + TRUE + + + + TRUE + + + + FALSE + + + + TRUE + + + + TRUE + + + + TRUE + + + + TRUE + + + + FALSE + + + + TRUE + + + + FALSE + + + + FALSE + + + + FALSE + + + + FALSE + + + + TRUE + + + + FALSE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/msautotest/wxs/expected/wfs_combined_filter.xml b/msautotest/wxs/expected/wfs_combined_filter.xml new file mode 100644 index 0000000000..671c6f93d4 --- /dev/null +++ b/msautotest/wxs/expected/wfs_combined_filter.xml @@ -0,0 +1,41 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 2442115.250000,245881.250000 2446614.500000,262496.843750 + + + + + + + 2442115.250000,245881.250000 2446614.500000,262496.843750 + + + + + 2442115.250000,262496.843750 2442339.750000,261851.750000 2446590.500000,249634.640625 2446614.500000,245881.250000 + + + 754 + 785 + 0 + 0 + 17371.988 + 1523 + 67 + Trans-Canada Highway + route Transcanadienne + + + + diff --git a/msautotest/wxs/expected/wfs_filter_false_ogr_property_is_equal_and_bbox.xml b/msautotest/wxs/expected/wfs_filter_false_ogr_property_is_equal_and_bbox.xml new file mode 100644 index 0000000000..8dd614faae --- /dev/null +++ b/msautotest/wxs/expected/wfs_filter_false_ogr_property_is_equal_and_bbox.xml @@ -0,0 +1,49 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + -65.816024,44.611049 -65.816024,44.611049 + + + + + + + -65.816024,44.611049 -65.816024,44.611049 + + + + + -65.816024,44.611049 + + + 0.000 + 0.000 + 118 + 2 + CAJOA + Digby + + + + + 12 + 021A12 + 443700 + 654600 + 1203006 + 0 + 2 + + + + diff --git a/msautotest/wxs/expected/wfs_filter_postgis_property_is_equal_empty.xml b/msautotest/wxs/expected/wfs_filter_postgis_property_is_equal_empty.xml new file mode 100644 index 0000000000..f0efb1032b --- /dev/null +++ b/msautotest/wxs/expected/wfs_filter_postgis_property_is_equal_empty.xml @@ -0,0 +1,16 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + missing + + + diff --git a/msautotest/wxs/expected/wfs_filter_postgis_property_is_null_result.xml b/msautotest/wxs/expected/wfs_filter_postgis_property_is_null_result.xml new file mode 100644 index 0000000000..47f8886b72 --- /dev/null +++ b/msautotest/wxs/expected/wfs_filter_postgis_property_is_null_result.xml @@ -0,0 +1,51 @@ +Content-Type: text/xml; subtype=gml/3.1.1; charset=UTF-8 + + + + + + 46.980843 -64.052355 + 46.980843 -64.052355 + + + + + + + 46.980843 -64.052355 + 46.980843 -64.052355 + + + + + 46.980843 -64.052355 + + + 1 + 0 + 0 + 8 + 1 + BACMK + "Tignish + + + + + 11 + 021I16 + 465700 + 640200 + 0 + 0 + 1 + + + + diff --git a/msautotest/wxs/expected/wfs_filter_postgis_property_is_null_zero_result.xml b/msautotest/wxs/expected/wfs_filter_postgis_property_is_null_zero_result.xml new file mode 100644 index 0000000000..2f19f5cb20 --- /dev/null +++ b/msautotest/wxs/expected/wfs_filter_postgis_property_is_null_zero_result.xml @@ -0,0 +1,15 @@ +Content-Type: text/xml; subtype=gml/3.1.1; charset=UTF-8 + + + + + missing + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_01.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_01.xml new file mode 100644 index 0000000000..5eaeac9fc7 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_01.xml @@ -0,0 +1,133 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 660036.840000,4879402.970000 690357.250000,4892926.890000 + + + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + 660036.840000,4885407.410000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + + + + 672279.270000,4879402.970000 672279.270000,4879402.970000 + + + + + 672279.270000,4879402.970000 + + + Vernio + 5535 + 1 + 0 + 0 + + + + + + + 666989.570000,4892926.890000 666989.570000,4892926.890000 + + + + + 666989.570000,4892926.890000 + + + Camugnano + 2132 + 1 + 0 + 0 + + + + + + + 662773.000000,4891987.410000 662773.000000,4891987.410000 + + + + + 662773.000000,4891987.410000 + + + Castel di Casio + 3174 + 1 + 0 + 0 + + + + + + + 673068.120000,4889949.750000 673068.120000,4889949.750000 + + + + + 673068.120000,4889949.750000 + + + Castiglione dei Pepoli + 6008 + 1 + 0 + 0 + + + + + + + 690357.250000,4888070.830000 690357.250000,4888070.830000 + + + + + 690357.250000,4888070.830000 + + + Firenzuola + 4812 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_01_spatial_index_disabled.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_01_spatial_index_disabled.xml new file mode 100644 index 0000000000..f43af8e2b2 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_01_spatial_index_disabled.xml @@ -0,0 +1,133 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 660036.840000,4879402.970000 690357.250000,4892926.890000 + + + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + 660036.840000,4885407.410000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + + + + 672279.270000,4879402.970000 672279.270000,4879402.970000 + + + + + 672279.270000,4879402.970000 + + + Vernio + 5535 + 1 + 0 + 0 + + + + + + + 666989.570000,4892926.890000 666989.570000,4892926.890000 + + + + + 666989.570000,4892926.890000 + + + Camugnano + 2132 + 1 + 0 + 0 + + + + + + + 662773.000000,4891987.410000 662773.000000,4891987.410000 + + + + + 662773.000000,4891987.410000 + + + Castel di Casio + 3174 + 1 + 0 + 0 + + + + + + + 673068.120000,4889949.750000 673068.120000,4889949.750000 + + + + + 673068.120000,4889949.750000 + + + Castiglione dei Pepoli + 6008 + 1 + 0 + 0 + + + + + + + 690357.250000,4888070.830000 690357.250000,4888070.830000 + + + + + 690357.250000,4888070.830000 + + + Firenzuola + 4812 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_02.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_02.xml new file mode 100644 index 0000000000..e5774bf484 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_02.xml @@ -0,0 +1,38 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + 643513.360000,4896928.190000 + + + Fanano + 2910 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_03.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_03.xml new file mode 100644 index 0000000000..8d82f6e06a --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_03.xml @@ -0,0 +1,152 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 643513.360000,4879402.970000 690357.250000,4896928.190000 + + + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + 660036.840000,4885407.410000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + + + + 672279.270000,4879402.970000 672279.270000,4879402.970000 + + + + + 672279.270000,4879402.970000 + + + Vernio + 5535 + 1 + 0 + 0 + + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + 643513.360000,4896928.190000 + + + Fanano + 2910 + 1 + 0 + 0 + + + + + + + 666989.570000,4892926.890000 666989.570000,4892926.890000 + + + + + 666989.570000,4892926.890000 + + + Camugnano + 2132 + 1 + 0 + 0 + + + + + + + 662773.000000,4891987.410000 662773.000000,4891987.410000 + + + + + 662773.000000,4891987.410000 + + + Castel di Casio + 3174 + 1 + 0 + 0 + + + + + + + 673068.120000,4889949.750000 673068.120000,4889949.750000 + + + + + 673068.120000,4889949.750000 + + + Castiglione dei Pepoli + 6008 + 1 + 0 + 0 + + + + + + + 690357.250000,4888070.830000 690357.250000,4888070.830000 + + + + + 690357.250000,4888070.830000 + + + Firenzuola + 4812 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_04.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_04.xml new file mode 100644 index 0000000000..29b9e62172 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_04.xml @@ -0,0 +1,114 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 662773.000000,4879402.970000 690357.250000,4892926.890000 + + + + + + + + 672279.270000,4879402.970000 672279.270000,4879402.970000 + + + + + 672279.270000,4879402.970000 + + + Vernio + 5535 + 1 + 0 + 0 + + + + + + + 666989.570000,4892926.890000 666989.570000,4892926.890000 + + + + + 666989.570000,4892926.890000 + + + Camugnano + 2132 + 1 + 0 + 0 + + + + + + + 662773.000000,4891987.410000 662773.000000,4891987.410000 + + + + + 662773.000000,4891987.410000 + + + Castel di Casio + 3174 + 1 + 0 + 0 + + + + + + + 673068.120000,4889949.750000 673068.120000,4889949.750000 + + + + + 673068.120000,4889949.750000 + + + Castiglione dei Pepoli + 6008 + 1 + 0 + 0 + + + + + + + 690357.250000,4888070.830000 690357.250000,4888070.830000 + + + + + 690357.250000,4888070.830000 + + + Firenzuola + 4812 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_05.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_05.xml new file mode 100644 index 0000000000..e5774bf484 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_05.xml @@ -0,0 +1,38 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + 643513.360000,4896928.190000 + + + Fanano + 2910 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_06.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_06.xml new file mode 100644 index 0000000000..e5774bf484 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_06.xml @@ -0,0 +1,38 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + 643513.360000,4896928.190000 + + + Fanano + 2910 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_06_disable_default_extent_for_getfeature.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_06_disable_default_extent_for_getfeature.xml new file mode 100644 index 0000000000..0528913985 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_06_disable_default_extent_for_getfeature.xml @@ -0,0 +1,38 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + 643513.360000,4896928.190000 + + + Fanano + 2910 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_07.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_07.xml new file mode 100644 index 0000000000..e5774bf484 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_07.xml @@ -0,0 +1,38 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + 643513.360000,4896928.190000 + + + Fanano + 2910 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_08.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_08.xml new file mode 100644 index 0000000000..87b9d1caba --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_08.xml @@ -0,0 +1,798 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 637137.640000,4865176.120000 710195.300000,4905916.470000 + + + + + + + + 672130.720000,4902785.470000 672130.720000,4902785.470000 + + + + + 672130.720000,4902785.470000 + + + Grizzana Morandi + 3694 + 1 + 0 + 0 + + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + 660036.840000,4885407.410000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + + + + 666678.760000,4876424.900000 666678.760000,4876424.900000 + + + + + 666678.760000,4876424.900000 + + + Cantagallo + 2820 + 1 + 0 + 0 + + + + + + + 656907.120000,4886687.840000 656907.120000,4886687.840000 + + + + + 656907.120000,4886687.840000 + + + Granaglione + 2116 + 1 + 0 + 0 + + + + + + + 663058.320000,4865176.120000 663058.320000,4865176.120000 + + + + + 663058.320000,4865176.120000 + + + Montemurlo + 17502 + 1 + 0 + 0 + + + + + + + 672279.270000,4879402.970000 672279.270000,4879402.970000 + + + + + 672279.270000,4879402.970000 + + + Vernio + 5535 + 1 + 0 + 0 + + + + + + + 637137.640000,4900625.560000 637137.640000,4900625.560000 + + + + + 637137.640000,4900625.560000 + + + Montecreto + 929 + 1 + 0 + 0 + + + + + + + 655146.140000,4903917.010000 655146.140000,4903917.010000 + + + + + 655146.140000,4903917.010000 + + + Montese + 3181 + 1 + 0 + 0 + + + + + + + 641470.510000,4898995.210000 641470.510000,4898995.210000 + + + + + 641470.510000,4898995.210000 + + + Sestola + 2670 + 1 + 0 + 0 + + + + + + + 666989.570000,4892926.890000 666989.570000,4892926.890000 + + + + + 666989.570000,4892926.890000 + + + Camugnano + 2132 + 1 + 0 + 0 + + + + + + + 662773.000000,4891987.410000 662773.000000,4891987.410000 + + + + + 662773.000000,4891987.410000 + + + Castel di Casio + 3174 + 1 + 0 + 0 + + + + + + + 673068.120000,4889949.750000 673068.120000,4889949.750000 + + + + + 673068.120000,4889949.750000 + + + Castiglione dei Pepoli + 6008 + 1 + 0 + 0 + + + + + + + 651437.840000,4891594.120000 651437.840000,4891594.120000 + + + + + 651437.840000,4891594.120000 + + + Lizzano in Belvedere + 2253 + 1 + 0 + 0 + + + + + + + 680854.530000,4905388.460000 680854.530000,4905388.460000 + + + + + 680854.530000,4905388.460000 + + + Monzuno + 5254 + 1 + 0 + 0 + + + + + + + 678374.680000,4898206.120000 678374.680000,4898206.120000 + + + + + 678374.680000,4898206.120000 + + + San Benedetto Val di Sambro + 4375 + 1 + 0 + 0 + + + + + + + 640503.540000,4884416.920000 640503.540000,4884416.920000 + + + + + 640503.540000,4884416.920000 + + + Cutigliano + 1699 + 1 + 0 + 0 + + + + + + + 641450.940000,4876458.530000 641450.940000,4876458.530000 + + + + + 641450.940000,4876458.530000 + + + Piteglio + 1877 + 1 + 0 + 0 + + + + + + + 690357.250000,4888070.830000 690357.250000,4888070.830000 + + + + + 690357.250000,4888070.830000 + + + Firenzuola + 4812 + 1 + 0 + 0 + + + + + + + 710195.300000,4866937.690000 710195.300000,4866937.690000 + + + + + 710195.300000,4866937.690000 + + + San Godenzo + 1187 + 1 + 0 + 0 + + + + + + + 686481.160000,4870207.090000 686481.160000,4870207.090000 + + + + + 686481.160000,4870207.090000 + + + San Piero a Sieve + 3758 + 1 + 0 + 0 + + + + + + + 697335.810000,4867309.060000 697335.810000,4867309.060000 + + + + + 697335.810000,4867309.060000 + + + Vicchio + 7145 + 1 + 0 + 0 + + + + + + + 670374.330000,4868394.460000 670374.330000,4868394.460000 + + + + + 670374.330000,4868394.460000 + + + Vaiano + 9051 + 1 + 0 + 0 + + + + + + + 659557.040000,4904456.570000 659557.040000,4904456.570000 + + + + + 659557.040000,4904456.570000 + + + Castel d'Aiano + 1822 + 1 + 0 + 0 + + + + + + + 700027.210000,4898730.810000 700027.210000,4898730.810000 + + + + + 700027.210000,4898730.810000 + + + Castel del Rio + 1252 + 1 + 0 + 0 + + + + + + + 654456.480000,4895565.290000 654456.480000,4895565.290000 + + + + + 654456.480000,4895565.290000 + + + Gaggio Montano + 4771 + 1 + 0 + 0 + + + + + + + 685837.450000,4904282.990000 685837.450000,4904282.990000 + + + + + 685837.450000,4904282.990000 + + + Loiano + 4158 + 1 + 0 + 0 + + + + + + + 685896.740000,4899660.120000 685896.740000,4899660.120000 + + + + + 685896.740000,4899660.120000 + + + Monghidoro + 3618 + 1 + 0 + 0 + + + + + + + 657705.770000,4891441.560000 657705.770000,4891441.560000 + + + + + 657705.770000,4891441.560000 + + + Porretta Terme + 4646 + 1 + 0 + 0 + + + + + + + 668148.550000,4905427.520000 668148.550000,4905427.520000 + + + + + 668148.550000,4905427.520000 + + + Vergato + 6730 + 1 + 0 + 0 + + + + + + + 642083.400000,4866048.770000 642083.400000,4866048.770000 + + + + + 642083.400000,4866048.770000 + + + Marliana + 2917 + 1 + 0 + 0 + + + + + + + 661896.570000,4866692.430000 661896.570000,4866692.430000 + + + + + 661896.570000,4866692.430000 + + + Montale + 10143 + 1 + 0 + 0 + + + + + + + 643529.070000,4879703.820000 643529.070000,4879703.820000 + + + + + 643529.070000,4879703.820000 + + + San Marcello Pistoiese + 7142 + 1 + 0 + 0 + + + + + + + 679352.610000,4874600.650000 679352.610000,4874600.650000 + + + + + 679352.610000,4874600.650000 + + + Barberino di Mugello + 9531 + 1 + 0 + 0 + + + + + + + 691242.090000,4869675.970000 691242.090000,4869675.970000 + + + + + 691242.090000,4869675.970000 + + + Borgo San Lorenzo + 15825 + 1 + 0 + 0 + + + + + + + 688742.950000,4873672.850000 688742.950000,4873672.850000 + + + + + 688742.950000,4873672.850000 + + + Scarperia + 6778 + 1 + 0 + 0 + + + + + + + 709203.270000,4883473.950000 709203.270000,4883473.950000 + + + + + 709203.270000,4883473.950000 + + + Marradi + 3617 + 1 + 0 + 0 + + + + + + + 703892.440000,4887624.730000 703892.440000,4887624.730000 + + + + + 703892.440000,4887624.730000 + + + Palazzuolo sul Senio + 1301 + 1 + 0 + 0 + + + + + + + 706612.320000,4905916.470000 706612.320000,4905916.470000 + + + + + 706612.320000,4905916.470000 + + + Borgo Tossignano + 3023 + 1 + 0 + 0 + + + + + + + 709517.650000,4900008.460000 709517.650000,4900008.460000 + + + + + 709517.650000,4900008.460000 + + + Casola Valsenio + 2844 + 1 + 0 + 0 + + + + + + + 704327.740000,4903948.540000 704327.740000,4903948.540000 + + + + + 704327.740000,4903948.540000 + + + Fontanelice + 1797 + 1 + 0 + 0 + + + + + + + 653901.530000,4866278.050000 653901.530000,4866278.050000 + + + + + 653901.530000,4866278.050000 + + + Pistoia + 84274 + 1 + 1 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_09.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_09.xml new file mode 100644 index 0000000000..322f96b3a8 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_09.xml @@ -0,0 +1,817 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 637137.640000,4865176.120000 710195.300000,4905916.470000 + + + + + + + + 672130.720000,4902785.470000 672130.720000,4902785.470000 + + + + + 672130.720000,4902785.470000 + + + Grizzana Morandi + 3694 + 1 + 0 + 0 + + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + 660036.840000,4885407.410000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + + + + 666678.760000,4876424.900000 666678.760000,4876424.900000 + + + + + 666678.760000,4876424.900000 + + + Cantagallo + 2820 + 1 + 0 + 0 + + + + + + + 656907.120000,4886687.840000 656907.120000,4886687.840000 + + + + + 656907.120000,4886687.840000 + + + Granaglione + 2116 + 1 + 0 + 0 + + + + + + + 663058.320000,4865176.120000 663058.320000,4865176.120000 + + + + + 663058.320000,4865176.120000 + + + Montemurlo + 17502 + 1 + 0 + 0 + + + + + + + 672279.270000,4879402.970000 672279.270000,4879402.970000 + + + + + 672279.270000,4879402.970000 + + + Vernio + 5535 + 1 + 0 + 0 + + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + 643513.360000,4896928.190000 + + + Fanano + 2910 + 1 + 0 + 0 + + + + + + + 637137.640000,4900625.560000 637137.640000,4900625.560000 + + + + + 637137.640000,4900625.560000 + + + Montecreto + 929 + 1 + 0 + 0 + + + + + + + 655146.140000,4903917.010000 655146.140000,4903917.010000 + + + + + 655146.140000,4903917.010000 + + + Montese + 3181 + 1 + 0 + 0 + + + + + + + 641470.510000,4898995.210000 641470.510000,4898995.210000 + + + + + 641470.510000,4898995.210000 + + + Sestola + 2670 + 1 + 0 + 0 + + + + + + + 666989.570000,4892926.890000 666989.570000,4892926.890000 + + + + + 666989.570000,4892926.890000 + + + Camugnano + 2132 + 1 + 0 + 0 + + + + + + + 662773.000000,4891987.410000 662773.000000,4891987.410000 + + + + + 662773.000000,4891987.410000 + + + Castel di Casio + 3174 + 1 + 0 + 0 + + + + + + + 673068.120000,4889949.750000 673068.120000,4889949.750000 + + + + + 673068.120000,4889949.750000 + + + Castiglione dei Pepoli + 6008 + 1 + 0 + 0 + + + + + + + 651437.840000,4891594.120000 651437.840000,4891594.120000 + + + + + 651437.840000,4891594.120000 + + + Lizzano in Belvedere + 2253 + 1 + 0 + 0 + + + + + + + 680854.530000,4905388.460000 680854.530000,4905388.460000 + + + + + 680854.530000,4905388.460000 + + + Monzuno + 5254 + 1 + 0 + 0 + + + + + + + 678374.680000,4898206.120000 678374.680000,4898206.120000 + + + + + 678374.680000,4898206.120000 + + + San Benedetto Val di Sambro + 4375 + 1 + 0 + 0 + + + + + + + 640503.540000,4884416.920000 640503.540000,4884416.920000 + + + + + 640503.540000,4884416.920000 + + + Cutigliano + 1699 + 1 + 0 + 0 + + + + + + + 641450.940000,4876458.530000 641450.940000,4876458.530000 + + + + + 641450.940000,4876458.530000 + + + Piteglio + 1877 + 1 + 0 + 0 + + + + + + + 690357.250000,4888070.830000 690357.250000,4888070.830000 + + + + + 690357.250000,4888070.830000 + + + Firenzuola + 4812 + 1 + 0 + 0 + + + + + + + 710195.300000,4866937.690000 710195.300000,4866937.690000 + + + + + 710195.300000,4866937.690000 + + + San Godenzo + 1187 + 1 + 0 + 0 + + + + + + + 686481.160000,4870207.090000 686481.160000,4870207.090000 + + + + + 686481.160000,4870207.090000 + + + San Piero a Sieve + 3758 + 1 + 0 + 0 + + + + + + + 697335.810000,4867309.060000 697335.810000,4867309.060000 + + + + + 697335.810000,4867309.060000 + + + Vicchio + 7145 + 1 + 0 + 0 + + + + + + + 670374.330000,4868394.460000 670374.330000,4868394.460000 + + + + + 670374.330000,4868394.460000 + + + Vaiano + 9051 + 1 + 0 + 0 + + + + + + + 659557.040000,4904456.570000 659557.040000,4904456.570000 + + + + + 659557.040000,4904456.570000 + + + Castel d'Aiano + 1822 + 1 + 0 + 0 + + + + + + + 700027.210000,4898730.810000 700027.210000,4898730.810000 + + + + + 700027.210000,4898730.810000 + + + Castel del Rio + 1252 + 1 + 0 + 0 + + + + + + + 654456.480000,4895565.290000 654456.480000,4895565.290000 + + + + + 654456.480000,4895565.290000 + + + Gaggio Montano + 4771 + 1 + 0 + 0 + + + + + + + 685837.450000,4904282.990000 685837.450000,4904282.990000 + + + + + 685837.450000,4904282.990000 + + + Loiano + 4158 + 1 + 0 + 0 + + + + + + + 685896.740000,4899660.120000 685896.740000,4899660.120000 + + + + + 685896.740000,4899660.120000 + + + Monghidoro + 3618 + 1 + 0 + 0 + + + + + + + 657705.770000,4891441.560000 657705.770000,4891441.560000 + + + + + 657705.770000,4891441.560000 + + + Porretta Terme + 4646 + 1 + 0 + 0 + + + + + + + 668148.550000,4905427.520000 668148.550000,4905427.520000 + + + + + 668148.550000,4905427.520000 + + + Vergato + 6730 + 1 + 0 + 0 + + + + + + + 642083.400000,4866048.770000 642083.400000,4866048.770000 + + + + + 642083.400000,4866048.770000 + + + Marliana + 2917 + 1 + 0 + 0 + + + + + + + 661896.570000,4866692.430000 661896.570000,4866692.430000 + + + + + 661896.570000,4866692.430000 + + + Montale + 10143 + 1 + 0 + 0 + + + + + + + 643529.070000,4879703.820000 643529.070000,4879703.820000 + + + + + 643529.070000,4879703.820000 + + + San Marcello Pistoiese + 7142 + 1 + 0 + 0 + + + + + + + 679352.610000,4874600.650000 679352.610000,4874600.650000 + + + + + 679352.610000,4874600.650000 + + + Barberino di Mugello + 9531 + 1 + 0 + 0 + + + + + + + 691242.090000,4869675.970000 691242.090000,4869675.970000 + + + + + 691242.090000,4869675.970000 + + + Borgo San Lorenzo + 15825 + 1 + 0 + 0 + + + + + + + 688742.950000,4873672.850000 688742.950000,4873672.850000 + + + + + 688742.950000,4873672.850000 + + + Scarperia + 6778 + 1 + 0 + 0 + + + + + + + 709203.270000,4883473.950000 709203.270000,4883473.950000 + + + + + 709203.270000,4883473.950000 + + + Marradi + 3617 + 1 + 0 + 0 + + + + + + + 703892.440000,4887624.730000 703892.440000,4887624.730000 + + + + + 703892.440000,4887624.730000 + + + Palazzuolo sul Senio + 1301 + 1 + 0 + 0 + + + + + + + 706612.320000,4905916.470000 706612.320000,4905916.470000 + + + + + 706612.320000,4905916.470000 + + + Borgo Tossignano + 3023 + 1 + 0 + 0 + + + + + + + 709517.650000,4900008.460000 709517.650000,4900008.460000 + + + + + 709517.650000,4900008.460000 + + + Casola Valsenio + 2844 + 1 + 0 + 0 + + + + + + + 704327.740000,4903948.540000 704327.740000,4903948.540000 + + + + + 704327.740000,4903948.540000 + + + Fontanelice + 1797 + 1 + 0 + 0 + + + + + + + 653901.530000,4866278.050000 653901.530000,4866278.050000 + + + + + 653901.530000,4866278.050000 + + + Pistoia + 84274 + 1 + 1 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_10.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_10.xml new file mode 100644 index 0000000000..9cc921258e --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_10.xml @@ -0,0 +1,266 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 641450.940000,4866937.690000 710195.300000,4905427.520000 + + + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + 660036.840000,4885407.410000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + + + + 672279.270000,4879402.970000 672279.270000,4879402.970000 + + + + + 672279.270000,4879402.970000 + + + Vernio + 5535 + 1 + 0 + 0 + + + + + + + 641470.510000,4898995.210000 641470.510000,4898995.210000 + + + + + 641470.510000,4898995.210000 + + + Sestola + 2670 + 1 + 0 + 0 + + + + + + + 678374.680000,4898206.120000 678374.680000,4898206.120000 + + + + + 678374.680000,4898206.120000 + + + San Benedetto Val di Sambro + 4375 + 1 + 0 + 0 + + + + + + + 641450.940000,4876458.530000 641450.940000,4876458.530000 + + + + + 641450.940000,4876458.530000 + + + Piteglio + 1877 + 1 + 0 + 0 + + + + + + + 710195.300000,4866937.690000 710195.300000,4866937.690000 + + + + + 710195.300000,4866937.690000 + + + San Godenzo + 1187 + 1 + 0 + 0 + + + + + + + 686481.160000,4870207.090000 686481.160000,4870207.090000 + + + + + 686481.160000,4870207.090000 + + + San Piero a Sieve + 3758 + 1 + 0 + 0 + + + + + + + 697335.810000,4867309.060000 697335.810000,4867309.060000 + + + + + 697335.810000,4867309.060000 + + + Vicchio + 7145 + 1 + 0 + 0 + + + + + + + 670374.330000,4868394.460000 670374.330000,4868394.460000 + + + + + 670374.330000,4868394.460000 + + + Vaiano + 9051 + 1 + 0 + 0 + + + + + + + 657705.770000,4891441.560000 657705.770000,4891441.560000 + + + + + 657705.770000,4891441.560000 + + + Porretta Terme + 4646 + 1 + 0 + 0 + + + + + + + 668148.550000,4905427.520000 668148.550000,4905427.520000 + + + + + 668148.550000,4905427.520000 + + + Vergato + 6730 + 1 + 0 + 0 + + + + + + + 643529.070000,4879703.820000 643529.070000,4879703.820000 + + + + + 643529.070000,4879703.820000 + + + San Marcello Pistoiese + 7142 + 1 + 0 + 0 + + + + + + + 688742.950000,4873672.850000 688742.950000,4873672.850000 + + + + + 688742.950000,4873672.850000 + + + Scarperia + 6778 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_11.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_11.xml new file mode 100644 index 0000000000..e92ba3a9f1 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_11.xml @@ -0,0 +1,551 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 637137.640000,4865176.120000 709517.650000,4905916.470000 + + + + + + + + 672130.720000,4902785.470000 672130.720000,4902785.470000 + + + + + 672130.720000,4902785.470000 + + + Grizzana Morandi + 3694 + 1 + 0 + 0 + + + + + + + 666678.760000,4876424.900000 666678.760000,4876424.900000 + + + + + 666678.760000,4876424.900000 + + + Cantagallo + 2820 + 1 + 0 + 0 + + + + + + + 656907.120000,4886687.840000 656907.120000,4886687.840000 + + + + + 656907.120000,4886687.840000 + + + Granaglione + 2116 + 1 + 0 + 0 + + + + + + + 663058.320000,4865176.120000 663058.320000,4865176.120000 + + + + + 663058.320000,4865176.120000 + + + Montemurlo + 17502 + 1 + 0 + 0 + + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + 643513.360000,4896928.190000 + + + Fanano + 2910 + 1 + 0 + 0 + + + + + + + 637137.640000,4900625.560000 637137.640000,4900625.560000 + + + + + 637137.640000,4900625.560000 + + + Montecreto + 929 + 1 + 0 + 0 + + + + + + + 655146.140000,4903917.010000 655146.140000,4903917.010000 + + + + + 655146.140000,4903917.010000 + + + Montese + 3181 + 1 + 0 + 0 + + + + + + + 666989.570000,4892926.890000 666989.570000,4892926.890000 + + + + + 666989.570000,4892926.890000 + + + Camugnano + 2132 + 1 + 0 + 0 + + + + + + + 662773.000000,4891987.410000 662773.000000,4891987.410000 + + + + + 662773.000000,4891987.410000 + + + Castel di Casio + 3174 + 1 + 0 + 0 + + + + + + + 673068.120000,4889949.750000 673068.120000,4889949.750000 + + + + + 673068.120000,4889949.750000 + + + Castiglione dei Pepoli + 6008 + 1 + 0 + 0 + + + + + + + 651437.840000,4891594.120000 651437.840000,4891594.120000 + + + + + 651437.840000,4891594.120000 + + + Lizzano in Belvedere + 2253 + 1 + 0 + 0 + + + + + + + 680854.530000,4905388.460000 680854.530000,4905388.460000 + + + + + 680854.530000,4905388.460000 + + + Monzuno + 5254 + 1 + 0 + 0 + + + + + + + 640503.540000,4884416.920000 640503.540000,4884416.920000 + + + + + 640503.540000,4884416.920000 + + + Cutigliano + 1699 + 1 + 0 + 0 + + + + + + + 690357.250000,4888070.830000 690357.250000,4888070.830000 + + + + + 690357.250000,4888070.830000 + + + Firenzuola + 4812 + 1 + 0 + 0 + + + + + + + 659557.040000,4904456.570000 659557.040000,4904456.570000 + + + + + 659557.040000,4904456.570000 + + + Castel d'Aiano + 1822 + 1 + 0 + 0 + + + + + + + 700027.210000,4898730.810000 700027.210000,4898730.810000 + + + + + 700027.210000,4898730.810000 + + + Castel del Rio + 1252 + 1 + 0 + 0 + + + + + + + 654456.480000,4895565.290000 654456.480000,4895565.290000 + + + + + 654456.480000,4895565.290000 + + + Gaggio Montano + 4771 + 1 + 0 + 0 + + + + + + + 685837.450000,4904282.990000 685837.450000,4904282.990000 + + + + + 685837.450000,4904282.990000 + + + Loiano + 4158 + 1 + 0 + 0 + + + + + + + 685896.740000,4899660.120000 685896.740000,4899660.120000 + + + + + 685896.740000,4899660.120000 + + + Monghidoro + 3618 + 1 + 0 + 0 + + + + + + + 642083.400000,4866048.770000 642083.400000,4866048.770000 + + + + + 642083.400000,4866048.770000 + + + Marliana + 2917 + 1 + 0 + 0 + + + + + + + 661896.570000,4866692.430000 661896.570000,4866692.430000 + + + + + 661896.570000,4866692.430000 + + + Montale + 10143 + 1 + 0 + 0 + + + + + + + 679352.610000,4874600.650000 679352.610000,4874600.650000 + + + + + 679352.610000,4874600.650000 + + + Barberino di Mugello + 9531 + 1 + 0 + 0 + + + + + + + 691242.090000,4869675.970000 691242.090000,4869675.970000 + + + + + 691242.090000,4869675.970000 + + + Borgo San Lorenzo + 15825 + 1 + 0 + 0 + + + + + + + 709203.270000,4883473.950000 709203.270000,4883473.950000 + + + + + 709203.270000,4883473.950000 + + + Marradi + 3617 + 1 + 0 + 0 + + + + + + + 703892.440000,4887624.730000 703892.440000,4887624.730000 + + + + + 703892.440000,4887624.730000 + + + Palazzuolo sul Senio + 1301 + 1 + 0 + 0 + + + + + + + 706612.320000,4905916.470000 706612.320000,4905916.470000 + + + + + 706612.320000,4905916.470000 + + + Borgo Tossignano + 3023 + 1 + 0 + 0 + + + + + + + 709517.650000,4900008.460000 709517.650000,4900008.460000 + + + + + 709517.650000,4900008.460000 + + + Casola Valsenio + 2844 + 1 + 0 + 0 + + + + + + + 704327.740000,4903948.540000 704327.740000,4903948.540000 + + + + + 704327.740000,4903948.540000 + + + Fontanelice + 1797 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_12.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_12.xml new file mode 100644 index 0000000000..dd8f6d2f01 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_12.xml @@ -0,0 +1,285 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 641450.940000,4866278.050000 710195.300000,4905427.520000 + + + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + 660036.840000,4885407.410000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + + + + 672279.270000,4879402.970000 672279.270000,4879402.970000 + + + + + 672279.270000,4879402.970000 + + + Vernio + 5535 + 1 + 0 + 0 + + + + + + + 641470.510000,4898995.210000 641470.510000,4898995.210000 + + + + + 641470.510000,4898995.210000 + + + Sestola + 2670 + 1 + 0 + 0 + + + + + + + 678374.680000,4898206.120000 678374.680000,4898206.120000 + + + + + 678374.680000,4898206.120000 + + + San Benedetto Val di Sambro + 4375 + 1 + 0 + 0 + + + + + + + 641450.940000,4876458.530000 641450.940000,4876458.530000 + + + + + 641450.940000,4876458.530000 + + + Piteglio + 1877 + 1 + 0 + 0 + + + + + + + 710195.300000,4866937.690000 710195.300000,4866937.690000 + + + + + 710195.300000,4866937.690000 + + + San Godenzo + 1187 + 1 + 0 + 0 + + + + + + + 686481.160000,4870207.090000 686481.160000,4870207.090000 + + + + + 686481.160000,4870207.090000 + + + San Piero a Sieve + 3758 + 1 + 0 + 0 + + + + + + + 697335.810000,4867309.060000 697335.810000,4867309.060000 + + + + + 697335.810000,4867309.060000 + + + Vicchio + 7145 + 1 + 0 + 0 + + + + + + + 670374.330000,4868394.460000 670374.330000,4868394.460000 + + + + + 670374.330000,4868394.460000 + + + Vaiano + 9051 + 1 + 0 + 0 + + + + + + + 657705.770000,4891441.560000 657705.770000,4891441.560000 + + + + + 657705.770000,4891441.560000 + + + Porretta Terme + 4646 + 1 + 0 + 0 + + + + + + + 668148.550000,4905427.520000 668148.550000,4905427.520000 + + + + + 668148.550000,4905427.520000 + + + Vergato + 6730 + 1 + 0 + 0 + + + + + + + 643529.070000,4879703.820000 643529.070000,4879703.820000 + + + + + 643529.070000,4879703.820000 + + + San Marcello Pistoiese + 7142 + 1 + 0 + 0 + + + + + + + 688742.950000,4873672.850000 688742.950000,4873672.850000 + + + + + 688742.950000,4873672.850000 + + + Scarperia + 6778 + 1 + 0 + 0 + + + + + + + 653901.530000,4866278.050000 653901.530000,4866278.050000 + + + + + 653901.530000,4866278.050000 + + + Pistoia + 84274 + 1 + 1 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_13.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_13.xml new file mode 100644 index 0000000000..9d6d017ff8 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_13.xml @@ -0,0 +1,570 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 637137.640000,4865176.120000 709517.650000,4905916.470000 + + + + + + + + 672130.720000,4902785.470000 672130.720000,4902785.470000 + + + + + 672130.720000,4902785.470000 + + + Grizzana Morandi + 3694 + 1 + 0 + 0 + + + + + + + 666678.760000,4876424.900000 666678.760000,4876424.900000 + + + + + 666678.760000,4876424.900000 + + + Cantagallo + 2820 + 1 + 0 + 0 + + + + + + + 656907.120000,4886687.840000 656907.120000,4886687.840000 + + + + + 656907.120000,4886687.840000 + + + Granaglione + 2116 + 1 + 0 + 0 + + + + + + + 663058.320000,4865176.120000 663058.320000,4865176.120000 + + + + + 663058.320000,4865176.120000 + + + Montemurlo + 17502 + 1 + 0 + 0 + + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + 643513.360000,4896928.190000 + + + Fanano + 2910 + 1 + 0 + 0 + + + + + + + 637137.640000,4900625.560000 637137.640000,4900625.560000 + + + + + 637137.640000,4900625.560000 + + + Montecreto + 929 + 1 + 0 + 0 + + + + + + + 655146.140000,4903917.010000 655146.140000,4903917.010000 + + + + + 655146.140000,4903917.010000 + + + Montese + 3181 + 1 + 0 + 0 + + + + + + + 666989.570000,4892926.890000 666989.570000,4892926.890000 + + + + + 666989.570000,4892926.890000 + + + Camugnano + 2132 + 1 + 0 + 0 + + + + + + + 662773.000000,4891987.410000 662773.000000,4891987.410000 + + + + + 662773.000000,4891987.410000 + + + Castel di Casio + 3174 + 1 + 0 + 0 + + + + + + + 673068.120000,4889949.750000 673068.120000,4889949.750000 + + + + + 673068.120000,4889949.750000 + + + Castiglione dei Pepoli + 6008 + 1 + 0 + 0 + + + + + + + 651437.840000,4891594.120000 651437.840000,4891594.120000 + + + + + 651437.840000,4891594.120000 + + + Lizzano in Belvedere + 2253 + 1 + 0 + 0 + + + + + + + 680854.530000,4905388.460000 680854.530000,4905388.460000 + + + + + 680854.530000,4905388.460000 + + + Monzuno + 5254 + 1 + 0 + 0 + + + + + + + 640503.540000,4884416.920000 640503.540000,4884416.920000 + + + + + 640503.540000,4884416.920000 + + + Cutigliano + 1699 + 1 + 0 + 0 + + + + + + + 690357.250000,4888070.830000 690357.250000,4888070.830000 + + + + + 690357.250000,4888070.830000 + + + Firenzuola + 4812 + 1 + 0 + 0 + + + + + + + 659557.040000,4904456.570000 659557.040000,4904456.570000 + + + + + 659557.040000,4904456.570000 + + + Castel d'Aiano + 1822 + 1 + 0 + 0 + + + + + + + 700027.210000,4898730.810000 700027.210000,4898730.810000 + + + + + 700027.210000,4898730.810000 + + + Castel del Rio + 1252 + 1 + 0 + 0 + + + + + + + 654456.480000,4895565.290000 654456.480000,4895565.290000 + + + + + 654456.480000,4895565.290000 + + + Gaggio Montano + 4771 + 1 + 0 + 0 + + + + + + + 685837.450000,4904282.990000 685837.450000,4904282.990000 + + + + + 685837.450000,4904282.990000 + + + Loiano + 4158 + 1 + 0 + 0 + + + + + + + 685896.740000,4899660.120000 685896.740000,4899660.120000 + + + + + 685896.740000,4899660.120000 + + + Monghidoro + 3618 + 1 + 0 + 0 + + + + + + + 642083.400000,4866048.770000 642083.400000,4866048.770000 + + + + + 642083.400000,4866048.770000 + + + Marliana + 2917 + 1 + 0 + 0 + + + + + + + 661896.570000,4866692.430000 661896.570000,4866692.430000 + + + + + 661896.570000,4866692.430000 + + + Montale + 10143 + 1 + 0 + 0 + + + + + + + 679352.610000,4874600.650000 679352.610000,4874600.650000 + + + + + 679352.610000,4874600.650000 + + + Barberino di Mugello + 9531 + 1 + 0 + 0 + + + + + + + 691242.090000,4869675.970000 691242.090000,4869675.970000 + + + + + 691242.090000,4869675.970000 + + + Borgo San Lorenzo + 15825 + 1 + 0 + 0 + + + + + + + 709203.270000,4883473.950000 709203.270000,4883473.950000 + + + + + 709203.270000,4883473.950000 + + + Marradi + 3617 + 1 + 0 + 0 + + + + + + + 703892.440000,4887624.730000 703892.440000,4887624.730000 + + + + + 703892.440000,4887624.730000 + + + Palazzuolo sul Senio + 1301 + 1 + 0 + 0 + + + + + + + 706612.320000,4905916.470000 706612.320000,4905916.470000 + + + + + 706612.320000,4905916.470000 + + + Borgo Tossignano + 3023 + 1 + 0 + 0 + + + + + + + 709517.650000,4900008.460000 709517.650000,4900008.460000 + + + + + 709517.650000,4900008.460000 + + + Casola Valsenio + 2844 + 1 + 0 + 0 + + + + + + + 704327.740000,4903948.540000 704327.740000,4903948.540000 + + + + + 704327.740000,4903948.540000 + + + Fontanelice + 1797 + 1 + 0 + 0 + + + + + + + 653901.530000,4866278.050000 653901.530000,4866278.050000 + + + + + 653901.530000,4866278.050000 + + + Pistoia + 84274 + 1 + 1 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_14.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_14.xml new file mode 100644 index 0000000000..8128bad4ba --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_14.xml @@ -0,0 +1,38 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 653901.530000,4866278.050000 653901.530000,4866278.050000 + + + + + + + + 653901.530000,4866278.050000 653901.530000,4866278.050000 + + + + + 653901.530000,4866278.050000 + + + Pistoia + 84274 + 1 + 1 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_15.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_15.xml new file mode 100644 index 0000000000..594ad7a3f9 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_15.xml @@ -0,0 +1,190 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 637137.640000,4866937.690000 710195.300000,4904456.570000 + + + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + 660036.840000,4885407.410000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + + + + 637137.640000,4900625.560000 637137.640000,4900625.560000 + + + + + 637137.640000,4900625.560000 + + + Montecreto + 929 + 1 + 0 + 0 + + + + + + + 640503.540000,4884416.920000 640503.540000,4884416.920000 + + + + + 640503.540000,4884416.920000 + + + Cutigliano + 1699 + 1 + 0 + 0 + + + + + + + 641450.940000,4876458.530000 641450.940000,4876458.530000 + + + + + 641450.940000,4876458.530000 + + + Piteglio + 1877 + 1 + 0 + 0 + + + + + + + 710195.300000,4866937.690000 710195.300000,4866937.690000 + + + + + 710195.300000,4866937.690000 + + + San Godenzo + 1187 + 1 + 0 + 0 + + + + + + + 659557.040000,4904456.570000 659557.040000,4904456.570000 + + + + + 659557.040000,4904456.570000 + + + Castel d'Aiano + 1822 + 1 + 0 + 0 + + + + + + + 700027.210000,4898730.810000 700027.210000,4898730.810000 + + + + + 700027.210000,4898730.810000 + + + Castel del Rio + 1252 + 1 + 0 + 0 + + + + + + + 703892.440000,4887624.730000 703892.440000,4887624.730000 + + + + + 703892.440000,4887624.730000 + + + Palazzuolo sul Senio + 1301 + 1 + 0 + 0 + + + + + + + 704327.740000,4903948.540000 704327.740000,4903948.540000 + + + + + 704327.740000,4903948.540000 + + + Fontanelice + 1797 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_16.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_16.xml new file mode 100644 index 0000000000..db58f228c6 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_16.xml @@ -0,0 +1,57 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 653901.530000,4865176.120000 663058.320000,4866278.050000 + + + + + + + + 663058.320000,4865176.120000 663058.320000,4865176.120000 + + + + + 663058.320000,4865176.120000 + + + Montemurlo + 17502 + 1 + 0 + 0 + + + + + + + 653901.530000,4866278.050000 653901.530000,4866278.050000 + + + + + 653901.530000,4866278.050000 + + + Pistoia + 84274 + 1 + 1 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_17.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_17.xml new file mode 100644 index 0000000000..594ad7a3f9 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_17.xml @@ -0,0 +1,190 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 637137.640000,4866937.690000 710195.300000,4904456.570000 + + + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + 660036.840000,4885407.410000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + + + + 637137.640000,4900625.560000 637137.640000,4900625.560000 + + + + + 637137.640000,4900625.560000 + + + Montecreto + 929 + 1 + 0 + 0 + + + + + + + 640503.540000,4884416.920000 640503.540000,4884416.920000 + + + + + 640503.540000,4884416.920000 + + + Cutigliano + 1699 + 1 + 0 + 0 + + + + + + + 641450.940000,4876458.530000 641450.940000,4876458.530000 + + + + + 641450.940000,4876458.530000 + + + Piteglio + 1877 + 1 + 0 + 0 + + + + + + + 710195.300000,4866937.690000 710195.300000,4866937.690000 + + + + + 710195.300000,4866937.690000 + + + San Godenzo + 1187 + 1 + 0 + 0 + + + + + + + 659557.040000,4904456.570000 659557.040000,4904456.570000 + + + + + 659557.040000,4904456.570000 + + + Castel d'Aiano + 1822 + 1 + 0 + 0 + + + + + + + 700027.210000,4898730.810000 700027.210000,4898730.810000 + + + + + 700027.210000,4898730.810000 + + + Castel del Rio + 1252 + 1 + 0 + 0 + + + + + + + 703892.440000,4887624.730000 703892.440000,4887624.730000 + + + + + 703892.440000,4887624.730000 + + + Palazzuolo sul Senio + 1301 + 1 + 0 + 0 + + + + + + + 704327.740000,4903948.540000 704327.740000,4903948.540000 + + + + + 704327.740000,4903948.540000 + + + Fontanelice + 1797 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_18.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_18.xml new file mode 100644 index 0000000000..2ae6dafd46 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_18.xml @@ -0,0 +1,38 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + 660036.840000,4885407.410000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_19.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_19.xml new file mode 100644 index 0000000000..268ad66052 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_19.xml @@ -0,0 +1,171 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 640503.540000,4866937.690000 710195.300000,4904456.570000 + + + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + 660036.840000,4885407.410000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + + + + 640503.540000,4884416.920000 640503.540000,4884416.920000 + + + + + 640503.540000,4884416.920000 + + + Cutigliano + 1699 + 1 + 0 + 0 + + + + + + + 641450.940000,4876458.530000 641450.940000,4876458.530000 + + + + + 641450.940000,4876458.530000 + + + Piteglio + 1877 + 1 + 0 + 0 + + + + + + + 710195.300000,4866937.690000 710195.300000,4866937.690000 + + + + + 710195.300000,4866937.690000 + + + San Godenzo + 1187 + 1 + 0 + 0 + + + + + + + 659557.040000,4904456.570000 659557.040000,4904456.570000 + + + + + 659557.040000,4904456.570000 + + + Castel d'Aiano + 1822 + 1 + 0 + 0 + + + + + + + 700027.210000,4898730.810000 700027.210000,4898730.810000 + + + + + 700027.210000,4898730.810000 + + + Castel del Rio + 1252 + 1 + 0 + 0 + + + + + + + 703892.440000,4887624.730000 703892.440000,4887624.730000 + + + + + 703892.440000,4887624.730000 + + + Palazzuolo sul Senio + 1301 + 1 + 0 + 0 + + + + + + + 704327.740000,4903948.540000 704327.740000,4903948.540000 + + + + + 704327.740000,4903948.540000 + + + Fontanelice + 1797 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_20.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_20.xml new file mode 100644 index 0000000000..deb3877809 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_20.xml @@ -0,0 +1,95 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 668148.550000,4867309.060000 697335.810000,4905427.520000 + + + + + + + + 672279.270000,4879402.970000 672279.270000,4879402.970000 + + + + + 672279.270000,4879402.970000 + + + Vernio + 5535 + 1 + 0 + 0 + + + + + + + 697335.810000,4867309.060000 697335.810000,4867309.060000 + + + + + 697335.810000,4867309.060000 + + + Vicchio + 7145 + 1 + 0 + 0 + + + + + + + 670374.330000,4868394.460000 670374.330000,4868394.460000 + + + + + 670374.330000,4868394.460000 + + + Vaiano + 9051 + 1 + 0 + 0 + + + + + + + 668148.550000,4905427.520000 668148.550000,4905427.520000 + + + + + 668148.550000,4905427.520000 + + + Vergato + 6730 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_21.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_21.xml new file mode 100644 index 0000000000..deb3877809 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_21.xml @@ -0,0 +1,95 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 668148.550000,4867309.060000 697335.810000,4905427.520000 + + + + + + + + 672279.270000,4879402.970000 672279.270000,4879402.970000 + + + + + 672279.270000,4879402.970000 + + + Vernio + 5535 + 1 + 0 + 0 + + + + + + + 697335.810000,4867309.060000 697335.810000,4867309.060000 + + + + + 697335.810000,4867309.060000 + + + Vicchio + 7145 + 1 + 0 + 0 + + + + + + + 670374.330000,4868394.460000 670374.330000,4868394.460000 + + + + + 670374.330000,4868394.460000 + + + Vaiano + 9051 + 1 + 0 + 0 + + + + + + + 668148.550000,4905427.520000 668148.550000,4905427.520000 + + + + + 668148.550000,4905427.520000 + + + Vergato + 6730 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_22.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_22.xml new file mode 100644 index 0000000000..1df56b8433 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_22.xml @@ -0,0 +1,57 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 656907.120000,4886687.840000 672130.720000,4902785.470000 + + + + + + + + 672130.720000,4902785.470000 672130.720000,4902785.470000 + + + + + 672130.720000,4902785.470000 + + + Grizzana Morandi + 3694 + 1 + 0 + 0 + + + + + + + 656907.120000,4886687.840000 656907.120000,4886687.840000 + + + + + 656907.120000,4886687.840000 + + + Granaglione + 2116 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_23.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_23.xml new file mode 100644 index 0000000000..33838c3c46 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_23.xml @@ -0,0 +1,57 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 656907.120000,4885407.410000 660036.840000,4886687.840000 + + + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + 660036.840000,4885407.410000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + + + + 656907.120000,4886687.840000 656907.120000,4886687.840000 + + + + + 656907.120000,4886687.840000 + + + Granaglione + 2116 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_24.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_24.xml new file mode 100644 index 0000000000..b5c0b68909 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_24.xml @@ -0,0 +1,779 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 637137.640000,4865176.120000 710195.300000,4905916.470000 + + + + + + + + 672130.720000,4902785.470000 672130.720000,4902785.470000 + + + + + 672130.720000,4902785.470000 + + + Grizzana Morandi + 3694 + 1 + 0 + 0 + + + + + + + 666678.760000,4876424.900000 666678.760000,4876424.900000 + + + + + 666678.760000,4876424.900000 + + + Cantagallo + 2820 + 1 + 0 + 0 + + + + + + + 663058.320000,4865176.120000 663058.320000,4865176.120000 + + + + + 663058.320000,4865176.120000 + + + Montemurlo + 17502 + 1 + 0 + 0 + + + + + + + 672279.270000,4879402.970000 672279.270000,4879402.970000 + + + + + 672279.270000,4879402.970000 + + + Vernio + 5535 + 1 + 0 + 0 + + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + 643513.360000,4896928.190000 + + + Fanano + 2910 + 1 + 0 + 0 + + + + + + + 637137.640000,4900625.560000 637137.640000,4900625.560000 + + + + + 637137.640000,4900625.560000 + + + Montecreto + 929 + 1 + 0 + 0 + + + + + + + 655146.140000,4903917.010000 655146.140000,4903917.010000 + + + + + 655146.140000,4903917.010000 + + + Montese + 3181 + 1 + 0 + 0 + + + + + + + 641470.510000,4898995.210000 641470.510000,4898995.210000 + + + + + 641470.510000,4898995.210000 + + + Sestola + 2670 + 1 + 0 + 0 + + + + + + + 666989.570000,4892926.890000 666989.570000,4892926.890000 + + + + + 666989.570000,4892926.890000 + + + Camugnano + 2132 + 1 + 0 + 0 + + + + + + + 662773.000000,4891987.410000 662773.000000,4891987.410000 + + + + + 662773.000000,4891987.410000 + + + Castel di Casio + 3174 + 1 + 0 + 0 + + + + + + + 673068.120000,4889949.750000 673068.120000,4889949.750000 + + + + + 673068.120000,4889949.750000 + + + Castiglione dei Pepoli + 6008 + 1 + 0 + 0 + + + + + + + 651437.840000,4891594.120000 651437.840000,4891594.120000 + + + + + 651437.840000,4891594.120000 + + + Lizzano in Belvedere + 2253 + 1 + 0 + 0 + + + + + + + 680854.530000,4905388.460000 680854.530000,4905388.460000 + + + + + 680854.530000,4905388.460000 + + + Monzuno + 5254 + 1 + 0 + 0 + + + + + + + 678374.680000,4898206.120000 678374.680000,4898206.120000 + + + + + 678374.680000,4898206.120000 + + + San Benedetto Val di Sambro + 4375 + 1 + 0 + 0 + + + + + + + 640503.540000,4884416.920000 640503.540000,4884416.920000 + + + + + 640503.540000,4884416.920000 + + + Cutigliano + 1699 + 1 + 0 + 0 + + + + + + + 641450.940000,4876458.530000 641450.940000,4876458.530000 + + + + + 641450.940000,4876458.530000 + + + Piteglio + 1877 + 1 + 0 + 0 + + + + + + + 690357.250000,4888070.830000 690357.250000,4888070.830000 + + + + + 690357.250000,4888070.830000 + + + Firenzuola + 4812 + 1 + 0 + 0 + + + + + + + 710195.300000,4866937.690000 710195.300000,4866937.690000 + + + + + 710195.300000,4866937.690000 + + + San Godenzo + 1187 + 1 + 0 + 0 + + + + + + + 686481.160000,4870207.090000 686481.160000,4870207.090000 + + + + + 686481.160000,4870207.090000 + + + San Piero a Sieve + 3758 + 1 + 0 + 0 + + + + + + + 697335.810000,4867309.060000 697335.810000,4867309.060000 + + + + + 697335.810000,4867309.060000 + + + Vicchio + 7145 + 1 + 0 + 0 + + + + + + + 670374.330000,4868394.460000 670374.330000,4868394.460000 + + + + + 670374.330000,4868394.460000 + + + Vaiano + 9051 + 1 + 0 + 0 + + + + + + + 659557.040000,4904456.570000 659557.040000,4904456.570000 + + + + + 659557.040000,4904456.570000 + + + Castel d'Aiano + 1822 + 1 + 0 + 0 + + + + + + + 700027.210000,4898730.810000 700027.210000,4898730.810000 + + + + + 700027.210000,4898730.810000 + + + Castel del Rio + 1252 + 1 + 0 + 0 + + + + + + + 654456.480000,4895565.290000 654456.480000,4895565.290000 + + + + + 654456.480000,4895565.290000 + + + Gaggio Montano + 4771 + 1 + 0 + 0 + + + + + + + 685837.450000,4904282.990000 685837.450000,4904282.990000 + + + + + 685837.450000,4904282.990000 + + + Loiano + 4158 + 1 + 0 + 0 + + + + + + + 685896.740000,4899660.120000 685896.740000,4899660.120000 + + + + + 685896.740000,4899660.120000 + + + Monghidoro + 3618 + 1 + 0 + 0 + + + + + + + 657705.770000,4891441.560000 657705.770000,4891441.560000 + + + + + 657705.770000,4891441.560000 + + + Porretta Terme + 4646 + 1 + 0 + 0 + + + + + + + 668148.550000,4905427.520000 668148.550000,4905427.520000 + + + + + 668148.550000,4905427.520000 + + + Vergato + 6730 + 1 + 0 + 0 + + + + + + + 642083.400000,4866048.770000 642083.400000,4866048.770000 + + + + + 642083.400000,4866048.770000 + + + Marliana + 2917 + 1 + 0 + 0 + + + + + + + 661896.570000,4866692.430000 661896.570000,4866692.430000 + + + + + 661896.570000,4866692.430000 + + + Montale + 10143 + 1 + 0 + 0 + + + + + + + 643529.070000,4879703.820000 643529.070000,4879703.820000 + + + + + 643529.070000,4879703.820000 + + + San Marcello Pistoiese + 7142 + 1 + 0 + 0 + + + + + + + 679352.610000,4874600.650000 679352.610000,4874600.650000 + + + + + 679352.610000,4874600.650000 + + + Barberino di Mugello + 9531 + 1 + 0 + 0 + + + + + + + 691242.090000,4869675.970000 691242.090000,4869675.970000 + + + + + 691242.090000,4869675.970000 + + + Borgo San Lorenzo + 15825 + 1 + 0 + 0 + + + + + + + 688742.950000,4873672.850000 688742.950000,4873672.850000 + + + + + 688742.950000,4873672.850000 + + + Scarperia + 6778 + 1 + 0 + 0 + + + + + + + 709203.270000,4883473.950000 709203.270000,4883473.950000 + + + + + 709203.270000,4883473.950000 + + + Marradi + 3617 + 1 + 0 + 0 + + + + + + + 703892.440000,4887624.730000 703892.440000,4887624.730000 + + + + + 703892.440000,4887624.730000 + + + Palazzuolo sul Senio + 1301 + 1 + 0 + 0 + + + + + + + 706612.320000,4905916.470000 706612.320000,4905916.470000 + + + + + 706612.320000,4905916.470000 + + + Borgo Tossignano + 3023 + 1 + 0 + 0 + + + + + + + 709517.650000,4900008.460000 709517.650000,4900008.460000 + + + + + 709517.650000,4900008.460000 + + + Casola Valsenio + 2844 + 1 + 0 + 0 + + + + + + + 704327.740000,4903948.540000 704327.740000,4903948.540000 + + + + + 704327.740000,4903948.540000 + + + Fontanelice + 1797 + 1 + 0 + 0 + + + + + + + 653901.530000,4866278.050000 653901.530000,4866278.050000 + + + + + 653901.530000,4866278.050000 + + + Pistoia + 84274 + 1 + 1 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_25.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_25.xml new file mode 100644 index 0000000000..71c17c1a3c --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_25.xml @@ -0,0 +1,16 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + missing + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_26.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_26.xml new file mode 100644 index 0000000000..71c17c1a3c --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_26.xml @@ -0,0 +1,16 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + missing + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_27.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_27.xml new file mode 100644 index 0000000000..71c17c1a3c --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_27.xml @@ -0,0 +1,16 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + missing + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_28.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_28.xml new file mode 100644 index 0000000000..33838c3c46 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_28.xml @@ -0,0 +1,57 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 656907.120000,4885407.410000 660036.840000,4886687.840000 + + + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + 660036.840000,4885407.410000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + + + + 656907.120000,4886687.840000 656907.120000,4886687.840000 + + + + + 656907.120000,4886687.840000 + + + Granaglione + 2116 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_29.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_29.xml new file mode 100644 index 0000000000..71c17c1a3c --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_29.xml @@ -0,0 +1,16 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + missing + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_30.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_30.xml new file mode 100644 index 0000000000..f1e4e7e5bb --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_30.xml @@ -0,0 +1,38 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 662773.000000,4891987.410000 662773.000000,4891987.410000 + + + + + + + + 662773.000000,4891987.410000 662773.000000,4891987.410000 + + + + + 662773.000000,4891987.410000 + + + Castel di Casio + 3174 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_31.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_31.xml new file mode 100644 index 0000000000..9dc366bc42 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_31.xml @@ -0,0 +1,304 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 680854.530000,4866937.690000 710195.300000,4905916.470000 + + + + + + + + 680854.530000,4905388.460000 680854.530000,4905388.460000 + + + + + 680854.530000,4905388.460000 + + + Monzuno + 5254 + 1 + 0 + 0 + + + + + + + 690357.250000,4888070.830000 690357.250000,4888070.830000 + + + + + 690357.250000,4888070.830000 + + + Firenzuola + 4812 + 1 + 0 + 0 + + + + + + + 710195.300000,4866937.690000 710195.300000,4866937.690000 + + + + + 710195.300000,4866937.690000 + + + San Godenzo + 1187 + 1 + 0 + 0 + + + + + + + 686481.160000,4870207.090000 686481.160000,4870207.090000 + + + + + 686481.160000,4870207.090000 + + + San Piero a Sieve + 3758 + 1 + 0 + 0 + + + + + + + 697335.810000,4867309.060000 697335.810000,4867309.060000 + + + + + 697335.810000,4867309.060000 + + + Vicchio + 7145 + 1 + 0 + 0 + + + + + + + 700027.210000,4898730.810000 700027.210000,4898730.810000 + + + + + 700027.210000,4898730.810000 + + + Castel del Rio + 1252 + 1 + 0 + 0 + + + + + + + 685837.450000,4904282.990000 685837.450000,4904282.990000 + + + + + 685837.450000,4904282.990000 + + + Loiano + 4158 + 1 + 0 + 0 + + + + + + + 685896.740000,4899660.120000 685896.740000,4899660.120000 + + + + + 685896.740000,4899660.120000 + + + Monghidoro + 3618 + 1 + 0 + 0 + + + + + + + 691242.090000,4869675.970000 691242.090000,4869675.970000 + + + + + 691242.090000,4869675.970000 + + + Borgo San Lorenzo + 15825 + 1 + 0 + 0 + + + + + + + 688742.950000,4873672.850000 688742.950000,4873672.850000 + + + + + 688742.950000,4873672.850000 + + + Scarperia + 6778 + 1 + 0 + 0 + + + + + + + 709203.270000,4883473.950000 709203.270000,4883473.950000 + + + + + 709203.270000,4883473.950000 + + + Marradi + 3617 + 1 + 0 + 0 + + + + + + + 703892.440000,4887624.730000 703892.440000,4887624.730000 + + + + + 703892.440000,4887624.730000 + + + Palazzuolo sul Senio + 1301 + 1 + 0 + 0 + + + + + + + 706612.320000,4905916.470000 706612.320000,4905916.470000 + + + + + 706612.320000,4905916.470000 + + + Borgo Tossignano + 3023 + 1 + 0 + 0 + + + + + + + 709517.650000,4900008.460000 709517.650000,4900008.460000 + + + + + 709517.650000,4900008.460000 + + + Casola Valsenio + 2844 + 1 + 0 + 0 + + + + + + + 704327.740000,4903948.540000 704327.740000,4903948.540000 + + + + + 704327.740000,4903948.540000 + + + Fontanelice + 1797 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_32.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_32.xml new file mode 100644 index 0000000000..33838c3c46 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_32.xml @@ -0,0 +1,57 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 656907.120000,4885407.410000 660036.840000,4886687.840000 + + + + + + + + 660036.840000,4885407.410000 660036.840000,4885407.410000 + + + + + 660036.840000,4885407.410000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + + + + 656907.120000,4886687.840000 656907.120000,4886687.840000 + + + + + 656907.120000,4886687.840000 + + + Granaglione + 2116 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_33.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_33.xml new file mode 100644 index 0000000000..0e6557ae65 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_33.xml @@ -0,0 +1,38 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + 643513.360000,4896928.190000 + + + Fanano + 2910 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_34.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_34.xml new file mode 100644 index 0000000000..08cff05475 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_34.xml @@ -0,0 +1,38 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + 643513.360000,4896928.190000 + + + Fanano + 2910 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_35.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_35.xml new file mode 100644 index 0000000000..bac776f439 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_35.xml @@ -0,0 +1,38 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + 643513.360000,4896928.190000 + + + Fanano + 2910 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_36.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_36.xml new file mode 100644 index 0000000000..5a76adbc80 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_36.xml @@ -0,0 +1,38 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + + + + 643513.360000,4896928.190000 643513.360000,4896928.190000 + + + + + 643513.360000,4896928.190000 + + + Fanano + 2910 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_37.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_37.xml new file mode 100644 index 0000000000..f1e2cbabaf --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_37.xml @@ -0,0 +1,41 @@ +Content-Type: text/xml; subtype="gml/3.2.1"; charset=UTF-8 + + + + + + 656907.12000 4886687.84000 + 656907.12000 4886687.84000 + + + + + + + + 656907.12000 4886687.84000 + 656907.12000 4886687.84000 + + + + + 656907.12000 4886687.84000 + + + Granaglione + 2116 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_38.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_38.xml new file mode 100644 index 0000000000..595b51c57b --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_38.xml @@ -0,0 +1,39 @@ +Content-Type: text/xml; subtype="gml/3.2.1"; charset=UTF-8 + + + + + + 656907.12000 4886687.84000 + 656907.12000 4886687.84000 + + + + + + + + 656907.12000 4886687.84000 + 656907.12000 4886687.84000 + + + + + 656907.12000 4886687.84000 + + + Granaglione + 2116 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_39.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_39.xml new file mode 100644 index 0000000000..f3b6e9d5ad --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_39.xml @@ -0,0 +1,16 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + missing + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_40.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_40.xml new file mode 100644 index 0000000000..cbf4262126 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_40.xml @@ -0,0 +1,39 @@ +Content-Type: text/xml; subtype=gml/3.1.1; charset=UTF-8 + + + + + + 653901.530000 4866278.050000 + 653901.530000 4866278.050000 + + + + + + + + 653901.530000 4866278.050000 + 653901.530000 4866278.050000 + + + + + 653901.530000 4866278.050000 + + + + 84274 + 1 + 1 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_41.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_41.xml new file mode 100644 index 0000000000..53226d4adf --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_41.xml @@ -0,0 +1,797 @@ +Content-Type: text/xml; subtype=gml/2.1.2; charset=UTF-8 + + + + + + 637137.64000,4865176.12000 710195.30000,4905916.47000 + + + + + + + + 679352.61000,4874600.65000 679352.61000,4874600.65000 + + + + + 679352.61000,4874600.65000 + + + Barberino di Mugello + 9531 + 1 + 0 + 0 + + + + + + + 691242.09000,4869675.97000 691242.09000,4869675.97000 + + + + + 691242.09000,4869675.97000 + + + Borgo San Lorenzo + 15825 + 1 + 0 + 0 + + + + + + + 706612.32000,4905916.47000 706612.32000,4905916.47000 + + + + + 706612.32000,4905916.47000 + + + Borgo Tossignano + 3023 + 1 + 0 + 0 + + + + + + + 666989.57000,4892926.89000 666989.57000,4892926.89000 + + + + + 666989.57000,4892926.89000 + + + Camugnano + 2132 + 1 + 0 + 0 + + + + + + + 666678.76000,4876424.90000 666678.76000,4876424.90000 + + + + + 666678.76000,4876424.90000 + + + Cantagallo + 2820 + 1 + 0 + 0 + + + + + + + 709517.65000,4900008.46000 709517.65000,4900008.46000 + + + + + 709517.65000,4900008.46000 + + + Casola Valsenio + 2844 + 1 + 0 + 0 + + + + + + + 659557.04000,4904456.57000 659557.04000,4904456.57000 + + + + + 659557.04000,4904456.57000 + + + Castel d'Aiano + 1822 + 1 + 0 + 0 + + + + + + + 700027.21000,4898730.81000 700027.21000,4898730.81000 + + + + + 700027.21000,4898730.81000 + + + Castel del Rio + 1252 + 1 + 0 + 0 + + + + + + + 662773.00000,4891987.41000 662773.00000,4891987.41000 + + + + + 662773.00000,4891987.41000 + + + Castel di Casio + 3174 + 1 + 0 + 0 + + + + + + + 673068.12000,4889949.75000 673068.12000,4889949.75000 + + + + + 673068.12000,4889949.75000 + + + Castiglione dei Pepoli + 6008 + 1 + 0 + 0 + + + + + + + 640503.54000,4884416.92000 640503.54000,4884416.92000 + + + + + 640503.54000,4884416.92000 + + + Cutigliano + 1699 + 1 + 0 + 0 + + + + + + + 690357.25000,4888070.83000 690357.25000,4888070.83000 + + + + + 690357.25000,4888070.83000 + + + Firenzuola + 4812 + 1 + 0 + 0 + + + + + + + 704327.74000,4903948.54000 704327.74000,4903948.54000 + + + + + 704327.74000,4903948.54000 + + + Fontanelice + 1797 + 1 + 0 + 0 + + + + + + + 654456.48000,4895565.29000 654456.48000,4895565.29000 + + + + + 654456.48000,4895565.29000 + + + Gaggio Montano + 4771 + 1 + 0 + 0 + + + + + + + 656907.12000,4886687.84000 656907.12000,4886687.84000 + + + + + 656907.12000,4886687.84000 + + + Granaglione + 2116 + 1 + 0 + 0 + + + + + + + 672130.72000,4902785.47000 672130.72000,4902785.47000 + + + + + 672130.72000,4902785.47000 + + + Grizzana Morandi + 3694 + 1 + 0 + 0 + + + + + + + 651437.84000,4891594.12000 651437.84000,4891594.12000 + + + + + 651437.84000,4891594.12000 + + + Lizzano in Belvedere + 2253 + 1 + 0 + 0 + + + + + + + 685837.45000,4904282.99000 685837.45000,4904282.99000 + + + + + 685837.45000,4904282.99000 + + + Loiano + 4158 + 1 + 0 + 0 + + + + + + + 642083.40000,4866048.77000 642083.40000,4866048.77000 + + + + + 642083.40000,4866048.77000 + + + Marliana + 2917 + 1 + 0 + 0 + + + + + + + 709203.27000,4883473.95000 709203.27000,4883473.95000 + + + + + 709203.27000,4883473.95000 + + + Marradi + 3617 + 1 + 0 + 0 + + + + + + + 685896.74000,4899660.12000 685896.74000,4899660.12000 + + + + + 685896.74000,4899660.12000 + + + Monghidoro + 3618 + 1 + 0 + 0 + + + + + + + 661896.57000,4866692.43000 661896.57000,4866692.43000 + + + + + 661896.57000,4866692.43000 + + + Montale + 10143 + 1 + 0 + 0 + + + + + + + 637137.64000,4900625.56000 637137.64000,4900625.56000 + + + + + 637137.64000,4900625.56000 + + + Montecreto + 929 + 1 + 0 + 0 + + + + + + + 663058.32000,4865176.12000 663058.32000,4865176.12000 + + + + + 663058.32000,4865176.12000 + + + Montemurlo + 17502 + 1 + 0 + 0 + + + + + + + 655146.14000,4903917.01000 655146.14000,4903917.01000 + + + + + 655146.14000,4903917.01000 + + + Montese + 3181 + 1 + 0 + 0 + + + + + + + 680854.53000,4905388.46000 680854.53000,4905388.46000 + + + + + 680854.53000,4905388.46000 + + + Monzuno + 5254 + 1 + 0 + 0 + + + + + + + 703892.44000,4887624.73000 703892.44000,4887624.73000 + + + + + 703892.44000,4887624.73000 + + + Palazzuolo sul Senio + 1301 + 1 + 0 + 0 + + + + + + + 653901.53000,4866278.05000 653901.53000,4866278.05000 + + + + + 653901.53000,4866278.05000 + + + Pistoia + 84274 + 1 + 1 + 0 + + + + + + + 641450.94000,4876458.53000 641450.94000,4876458.53000 + + + + + 641450.94000,4876458.53000 + + + Piteglio + 1877 + 1 + 0 + 0 + + + + + + + 657705.77000,4891441.56000 657705.77000,4891441.56000 + + + + + 657705.77000,4891441.56000 + + + Porretta Terme + 4646 + 1 + 0 + 0 + + + + + + + 660036.84000,4885407.41000 660036.84000,4885407.41000 + + + + + 660036.84000,4885407.41000 + + + Sambuca Pistoiese + 1604 + 1 + 0 + 0 + + + + + + + 678374.68000,4898206.12000 678374.68000,4898206.12000 + + + + + 678374.68000,4898206.12000 + + + San Benedetto Val di Sambro + 4375 + 1 + 0 + 0 + + + + + + + 710195.30000,4866937.69000 710195.30000,4866937.69000 + + + + + 710195.30000,4866937.69000 + + + San Godenzo + 1187 + 1 + 0 + 0 + + + + + + + 643529.07000,4879703.82000 643529.07000,4879703.82000 + + + + + 643529.07000,4879703.82000 + + + San Marcello Pistoiese + 7142 + 1 + 0 + 0 + + + + + + + 686481.16000,4870207.09000 686481.16000,4870207.09000 + + + + + 686481.16000,4870207.09000 + + + San Piero a Sieve + 3758 + 1 + 0 + 0 + + + + + + + 688742.95000,4873672.85000 688742.95000,4873672.85000 + + + + + 688742.95000,4873672.85000 + + + Scarperia + 6778 + 1 + 0 + 0 + + + + + + + 641470.51000,4898995.21000 641470.51000,4898995.21000 + + + + + 641470.51000,4898995.21000 + + + Sestola + 2670 + 1 + 0 + 0 + + + + + + + 670374.33000,4868394.46000 670374.33000,4868394.46000 + + + + + 670374.33000,4868394.46000 + + + Vaiano + 9051 + 1 + 0 + 0 + + + + + + + 668148.55000,4905427.52000 668148.55000,4905427.52000 + + + + + 668148.55000,4905427.52000 + + + Vergato + 6730 + 1 + 0 + 0 + + + + + + + 672279.27000,4879402.97000 672279.27000,4879402.97000 + + + + + 672279.27000,4879402.97000 + + + Vernio + 5535 + 1 + 0 + 0 + + + + + + + 697335.81000,4867309.06000 697335.81000,4867309.06000 + + + + + 697335.81000,4867309.06000 + + + Vicchio + 7145 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_42.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_42.xml new file mode 100644 index 0000000000..6bbe411da3 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_42.xml @@ -0,0 +1,38 @@ +Content-Type: text/xml; subtype=gml/2.1.2; charset=UTF-8 + + + + + + 672130.72000,4902785.47000 672130.72000,4902785.47000 + + + + + + + + 672130.72000,4902785.47000 672130.72000,4902785.47000 + + + + + 672130.72000,4902785.47000 + + + Grizzana Morandi + 3694 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_native_sql_43.xml b/msautotest/wxs/expected/wfs_ogr_native_sql_43.xml new file mode 100644 index 0000000000..68a819bed4 --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_native_sql_43.xml @@ -0,0 +1,38 @@ +Content-Type: text/xml; subtype=gml/2.1.2; charset=UTF-8 + + + + + + 44.25795,11.15631 44.25795,11.15631 + + + + + + + + 44.25795,11.15631 44.25795,11.15631 + + + + + 44.25795,11.15631 + + + Grizzana Morandi + 3694 + 1 + 0 + 0 + + + + diff --git a/msautotest/wxs/expected/wfs_ogr_tileindex_of_shp_bbox_filter.xml b/msautotest/wxs/expected/wfs_ogr_tileindex_of_shp_bbox_filter.xml new file mode 100644 index 0000000000..6f0f1d98da --- /dev/null +++ b/msautotest/wxs/expected/wfs_ogr_tileindex_of_shp_bbox_filter.xml @@ -0,0 +1,33 @@ +Content-Type: text/xml; subtype="gml/3.2.1"; charset=UTF-8 + + + + + + 49.00000 2.00000 + 49.00000 2.00000 + + + + + + + 49.00000 2.00000 + 49.00000 2.00000 + + + + + 49.00000 2.00000 + + + + + + diff --git a/msautotest/wxs/expected/wfs_shape_tileindex_of_shp_bbox_filter.xml b/msautotest/wxs/expected/wfs_shape_tileindex_of_shp_bbox_filter.xml new file mode 100644 index 0000000000..6f0f1d98da --- /dev/null +++ b/msautotest/wxs/expected/wfs_shape_tileindex_of_shp_bbox_filter.xml @@ -0,0 +1,33 @@ +Content-Type: text/xml; subtype="gml/3.2.1"; charset=UTF-8 + + + + + + 49.00000 2.00000 + 49.00000 2.00000 + + + + + + + 49.00000 2.00000 + 49.00000 2.00000 + + + + + 49.00000 2.00000 + + + + + + diff --git a/msautotest/wxs/expected/wfs_test5299.xml b/msautotest/wxs/expected/wfs_test5299.xml new file mode 100644 index 0000000000..0741ac202b --- /dev/null +++ b/msautotest/wxs/expected/wfs_test5299.xml @@ -0,0 +1,45 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + 676763.746000,252977.057000 676992.160000,253159.650000 + + + + + + + 676763.746000,252977.057000 676992.160000,253159.650000 + + + + + + + + + 676881.746000,253159.650000 676952.500000,253142.812000 676984.539000,253076.568000 676992.160000,253047.552000 676907.575000,252978.182000 676793.971000,252977.057000 676763.746000,253101.446000 676881.746000,253159.650000 + + + + + 676881.746000,253159.650000 676835.762000,253108.566000 676841.704000,253079.649000 676870.271000,253078.765000 676924.143000,253120.438000 676881.746000,253159.650000 + + + + + + + + + + diff --git a/msautotest/wxs/expected/wfsogr_ogroutput_propertyname.txt b/msautotest/wxs/expected/wfsogr_ogroutput_propertyname.txt new file mode 100644 index 0000000000..4b5fd44aae --- /dev/null +++ b/msautotest/wxs/expected/wfsogr_ogroutput_propertyname.txt @@ -0,0 +1,40 @@ +Content-Type: multipart/mixed; boundary=xxOGRBoundaryxx + +--xxOGRBoundaryxx +Content-Disposition: attachment; filename=road.mid +Content-Type: application/binary +Content-Transfer-Encoding: binary + +"" + +--xxOGRBoundaryxx +Content-Disposition: attachment; filename=road.mif +Content-Type: application/binary +Content-Transfer-Encoding: binary + +Version 300 +Charset "Neutral" +Delimiter "," +CoordSys Earth Projection 3, 74, "m", -95, 49, 49, 77, 0, 0 +Columns 1 + NAME_E Char(26) +Data + +Pline 14 +2577257 430271.1875 +2577292 420127.65625 +2577297.5 418604.78125 +2577491.75 417462.90625 +2578069 415941.46875 +2578836.5 414230.25 +2579413.25 412899.1875 +2580247.5 412070.84375 +2580693.5 411149.46875 +2580978.5 408984.375 +2580750.5 407559.96875 +2580066.75 405736.6875 +2579326 403970.4375 +2578927.5 402717.03125 + Pen (1,2,0) + +--xxOGRBoundaryxx-- diff --git a/msautotest/wxs/expected/wms111_test_xml_escaping.xml b/msautotest/wxs/expected/wms111_test_xml_escaping.xml new file mode 100644 index 0000000000..b5e26022d2 --- /dev/null +++ b/msautotest/wxs/expected/wms111_test_xml_escaping.xml @@ -0,0 +1,142 @@ + + + ]> + + + + + OGC:WMS + title & title + abstract&abstract + + keyword&keyword + + + + + contactperson&contactperson + contactorganization&contactorganization + + contactposition&contactposition + + addresstype&addresstype +
address&address
+ city&city + stateorprovince&stateorprovince + postcode&postcode + country&country +
+ contactvoicetelephone&contactvoicetelephone + contactfacsimiletelephone&contactfacsimiletelephone + contactelectronicmailaddress&contactelectronicmailaddress +
+ fees&fees + accessconstraints&accessconstraints +
+ + + + + application/vnd.ogc.wms_xml + + + + + + + + + image/png + image/jpeg + image/png; mode=8bit + application/x-pdf + image/svg+xml + image/tiff + application/vnd.google-earth.kml+xml + application/vnd.google-earth.kmz + application/json + + + + + + + + + text/plain + application/vnd.ogc.gml + + + + + + + + + text/xml + + + + + + + + + image/png + image/jpeg + image/png; mode=8bit + + + + + + + + + text/xml + + + + + + + + + + application/vnd.ogc.se_xml + application/vnd.ogc.se_inimage + application/vnd.ogc.se_blank + + + + + XML_ESCAPE_TEST + title & title + abstract&abstract + + keyword&keyword + + EPSG:4326 + EPSG:4269 + + + + province + title&title + abstract&abstract + + + + + +
diff --git a/msautotest/wxs/expected/wms130_test_xml_escaping.xml b/msautotest/wxs/expected/wms130_test_xml_escaping.xml new file mode 100644 index 0000000000..983dec5abd --- /dev/null +++ b/msautotest/wxs/expected/wms130_test_xml_escaping.xml @@ -0,0 +1,148 @@ + + + + + WMS + title & title + abstract&abstract + + keyword&keyword + + + + + contactperson&contactperson + contactorganization&contactorganization + + contactposition&contactposition + + addresstype&addresstype +
address&address
+ city&city + stateorprovince&stateorprovince + postcode&postcode + country&country +
+ contactvoicetelephone&contactvoicetelephone + contactfacsimiletelephone&contactfacsimiletelephone + contactelectronicmailaddress&contactelectronicmailaddress +
+ fees&fees + accessconstraints&accessconstraints + 4096 + 4096 +
+ + + + + text/xml + + + + + + + + + image/png + image/jpeg + image/png; mode=8bit + application/x-pdf + image/svg+xml + image/tiff + application/vnd.google-earth.kml+xml + application/vnd.google-earth.kmz + application/json + + + + + + + + + text/plain + application/vnd.ogc.gml + + + + + + + + + text/xml + + + + + + + + + image/png + image/jpeg + image/png; mode=8bit + + + + + + + + + text/xml + + + + + + + + + + XML + INIMAGE + BLANK + + + + XML_ESCAPE_TEST + title & title + abstract&abstract + + keyword&keyword + + EPSG:4326 + EPSG:4269 + + -67.5725 + -58.9275 + 42 + 48.5 + + + + province + title&title + abstract&abstract + + -66.7243 + -57.7217 + 41.7705 + 48.4773 + + + + + +
diff --git a/msautotest/wxs/expected/wms_cap130.xml b/msautotest/wxs/expected/wms_cap130.xml index d3a6bcb741..beb6d4d0c9 100644 --- a/msautotest/wxs/expected/wms_cap130.xml +++ b/msautotest/wxs/expected/wms_cap130.xml @@ -33,8 +33,8 @@ Content-Type: text/xml; charset=UTF-8 None None 1 - 2048 - 2048 + 4096 + 4096 diff --git a/msautotest/wxs/expected/wms_cap130_postgis.xml b/msautotest/wxs/expected/wms_cap130_postgis.xml index d3a6bcb741..beb6d4d0c9 100644 --- a/msautotest/wxs/expected/wms_cap130_postgis.xml +++ b/msautotest/wxs/expected/wms_cap130_postgis.xml @@ -33,8 +33,8 @@ Content-Type: text/xml; charset=UTF-8 None None 1 - 2048 - 2048 + 4096 + 4096 diff --git a/msautotest/wxs/expected/wms_cap_latestversion.xml b/msautotest/wxs/expected/wms_cap_latestversion.xml index d3a6bcb741..beb6d4d0c9 100644 --- a/msautotest/wxs/expected/wms_cap_latestversion.xml +++ b/msautotest/wxs/expected/wms_cap_latestversion.xml @@ -33,8 +33,8 @@ Content-Type: text/xml; charset=UTF-8 None None 1 - 2048 - 2048 + 4096 + 4096 diff --git a/msautotest/wxs/expected/wms_cap_latestversion_postgis.xml b/msautotest/wxs/expected/wms_cap_latestversion_postgis.xml index d3a6bcb741..beb6d4d0c9 100644 --- a/msautotest/wxs/expected/wms_cap_latestversion_postgis.xml +++ b/msautotest/wxs/expected/wms_cap_latestversion_postgis.xml @@ -33,8 +33,8 @@ Content-Type: text/xml; charset=UTF-8 None None 1 - 2048 - 2048 + 4096 + 4096 diff --git a/msautotest/wxs/expected/wms_dimension_cap.xml b/msautotest/wxs/expected/wms_dimension_cap.xml index 93094b4c6e..7e6a171f97 100644 --- a/msautotest/wxs/expected/wms_dimension_cap.xml +++ b/msautotest/wxs/expected/wms_dimension_cap.xml @@ -37,6 +37,7 @@ Content-Type: application/vnd.ogc.wms_xml; charset=UTF-8 image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_dimension_cap130.xml b/msautotest/wxs/expected/wms_dimension_cap130.xml index 13864d7044..473c5da5fe 100644 --- a/msautotest/wxs/expected/wms_dimension_cap130.xml +++ b/msautotest/wxs/expected/wms_dimension_cap130.xml @@ -10,8 +10,8 @@ Content-Type: text/xml; charset=UTF-8 - 2048 - 2048 + 4096 + 4096 @@ -34,6 +34,7 @@ Content-Type: text/xml; charset=UTF-8 image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_empty_cap111.xml b/msautotest/wxs/expected/wms_empty_cap111.xml index fb62c307e6..68b59a4178 100644 --- a/msautotest/wxs/expected/wms_empty_cap111.xml +++ b/msautotest/wxs/expected/wms_empty_cap111.xml @@ -34,6 +34,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_empty_cap130.xml b/msautotest/wxs/expected/wms_empty_cap130.xml index 2e12eaf6c1..124a99b5ab 100644 --- a/msautotest/wxs/expected/wms_empty_cap130.xml +++ b/msautotest/wxs/expected/wms_empty_cap130.xml @@ -7,8 +7,8 @@ - 2048 - 2048 + 4096 + 4096 @@ -31,6 +31,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_empty_cap_latestversion.xml b/msautotest/wxs/expected/wms_empty_cap_latestversion.xml index 2e12eaf6c1..124a99b5ab 100644 --- a/msautotest/wxs/expected/wms_empty_cap_latestversion.xml +++ b/msautotest/wxs/expected/wms_empty_cap_latestversion.xml @@ -7,8 +7,8 @@ - 2048 - 2048 + 4096 + 4096 @@ -31,6 +31,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_get_capabilities_tileindexmixedsrs.xml b/msautotest/wxs/expected/wms_get_capabilities_tileindexmixedsrs.xml index a57c4ad98f..b2c9b7cba6 100644 --- a/msautotest/wxs/expected/wms_get_capabilities_tileindexmixedsrs.xml +++ b/msautotest/wxs/expected/wms_get_capabilities_tileindexmixedsrs.xml @@ -36,6 +36,7 @@ Content-Type: application/vnd.ogc.wms_xml; charset=UTF-8 image/svg+xml application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_grid_reproj_to_3857_non_square_pixels_beyond_validity.png b/msautotest/wxs/expected/wms_grid_reproj_to_3857_non_square_pixels_beyond_validity.png new file mode 100644 index 0000000000..1966daf623 Binary files /dev/null and b/msautotest/wxs/expected/wms_grid_reproj_to_3857_non_square_pixels_beyond_validity.png differ diff --git a/msautotest/wxs/expected/wms_grid_reproj_to_3857_square_pixels_beyond_validity.png b/msautotest/wxs/expected/wms_grid_reproj_to_3857_square_pixels_beyond_validity.png new file mode 100644 index 0000000000..bca97786e8 Binary files /dev/null and b/msautotest/wxs/expected/wms_grid_reproj_to_3857_square_pixels_beyond_validity.png differ diff --git a/msautotest/wxs/expected/wms_grid_reproj_to_3857_square_pixels_within_validity.png b/msautotest/wxs/expected/wms_grid_reproj_to_3857_square_pixels_within_validity.png new file mode 100644 index 0000000000..0466590656 Binary files /dev/null and b/msautotest/wxs/expected/wms_grid_reproj_to_3857_square_pixels_within_validity.png differ diff --git a/msautotest/wxs/expected/wms_inspire_cap.xml b/msautotest/wxs/expected/wms_inspire_cap.xml index 39bbafae3d..335d0a71e0 100644 --- a/msautotest/wxs/expected/wms_inspire_cap.xml +++ b/msautotest/wxs/expected/wms_inspire_cap.xml @@ -55,6 +55,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_inspire_cap_111.xml b/msautotest/wxs/expected/wms_inspire_cap_111.xml index 8fefc5f579..805d73f7d1 100644 --- a/msautotest/wxs/expected/wms_inspire_cap_111.xml +++ b/msautotest/wxs/expected/wms_inspire_cap_111.xml @@ -56,6 +56,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_inspire_cap_111_eng.xml b/msautotest/wxs/expected/wms_inspire_cap_111_eng.xml index 5a9e1f0d67..23b14008e1 100644 --- a/msautotest/wxs/expected/wms_inspire_cap_111_eng.xml +++ b/msautotest/wxs/expected/wms_inspire_cap_111_eng.xml @@ -56,6 +56,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_inspire_cap_111_ger.xml b/msautotest/wxs/expected/wms_inspire_cap_111_ger.xml index 8fefc5f579..805d73f7d1 100644 --- a/msautotest/wxs/expected/wms_inspire_cap_111_ger.xml +++ b/msautotest/wxs/expected/wms_inspire_cap_111_ger.xml @@ -56,6 +56,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_inspire_cap_eng.xml b/msautotest/wxs/expected/wms_inspire_cap_eng.xml index 86a9096ae0..eb1aaaa62b 100644 --- a/msautotest/wxs/expected/wms_inspire_cap_eng.xml +++ b/msautotest/wxs/expected/wms_inspire_cap_eng.xml @@ -55,6 +55,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_inspire_cap_ger.xml b/msautotest/wxs/expected/wms_inspire_cap_ger.xml index 39bbafae3d..335d0a71e0 100644 --- a/msautotest/wxs/expected/wms_inspire_cap_ger.xml +++ b/msautotest/wxs/expected/wms_inspire_cap_ger.xml @@ -55,6 +55,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_inspire_scenario1_cap130.xml b/msautotest/wxs/expected/wms_inspire_scenario1_cap130.xml index dc571bd190..a7b62ff4fb 100644 --- a/msautotest/wxs/expected/wms_inspire_scenario1_cap130.xml +++ b/msautotest/wxs/expected/wms_inspire_scenario1_cap130.xml @@ -29,8 +29,8 @@ conditions unknown None - 2048 - 2048 + 4096 + 4096 @@ -53,6 +53,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_inspire_scenario1_cap130_eng.xml b/msautotest/wxs/expected/wms_inspire_scenario1_cap130_eng.xml index dc571bd190..a7b62ff4fb 100644 --- a/msautotest/wxs/expected/wms_inspire_scenario1_cap130_eng.xml +++ b/msautotest/wxs/expected/wms_inspire_scenario1_cap130_eng.xml @@ -29,8 +29,8 @@ conditions unknown None - 2048 - 2048 + 4096 + 4096 @@ -53,6 +53,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_inspire_scenario1_cap130_ger.xml b/msautotest/wxs/expected/wms_inspire_scenario1_cap130_ger.xml index bb2a59272b..4036553968 100644 --- a/msautotest/wxs/expected/wms_inspire_scenario1_cap130_ger.xml +++ b/msautotest/wxs/expected/wms_inspire_scenario1_cap130_ger.xml @@ -29,8 +29,8 @@ conditions unknown None - 2048 - 2048 + 4096 + 4096 @@ -53,6 +53,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json @@ -89,7 +90,7 @@ TN.RoadTransportNetwork.RoadArea - Verkehrsnetze: Straßenfläche + Verkehrsnetze: Straßenfläche myroadareaabstractger myroadareakeyword1 @@ -124,7 +125,7 @@ TN.RoadTransportNetwork.RoadLink - Verkehrsnetze: Straßensegment + Verkehrsnetze: Straßensegment myroadlinklayerabstractger myroadlinklayerkeyword1 diff --git a/msautotest/wxs/expected/wms_inspire_scenario2_cap111.xml b/msautotest/wxs/expected/wms_inspire_scenario2_cap111.xml index 1d28a46a1d..51e80591aa 100644 --- a/msautotest/wxs/expected/wms_inspire_scenario2_cap111.xml +++ b/msautotest/wxs/expected/wms_inspire_scenario2_cap111.xml @@ -55,6 +55,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_inspire_scenario2_cap111_eng.xml b/msautotest/wxs/expected/wms_inspire_scenario2_cap111_eng.xml index 1d28a46a1d..51e80591aa 100644 --- a/msautotest/wxs/expected/wms_inspire_scenario2_cap111_eng.xml +++ b/msautotest/wxs/expected/wms_inspire_scenario2_cap111_eng.xml @@ -55,6 +55,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_inspire_scenario2_cap111_ger.xml b/msautotest/wxs/expected/wms_inspire_scenario2_cap111_ger.xml index 3598be3aa3..ca43fc49bd 100644 --- a/msautotest/wxs/expected/wms_inspire_scenario2_cap111_ger.xml +++ b/msautotest/wxs/expected/wms_inspire_scenario2_cap111_ger.xml @@ -55,6 +55,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json @@ -112,7 +113,7 @@ TN.RoadTransportNetwork.RoadArea - Verkehrsnetze: Straßenfläche + Verkehrsnetze: Straßenfläche myroadareaabstractger myroadareakeyword1 @@ -138,7 +139,7 @@ TN.RoadTransportNetwork.RoadLink - Verkehrsnetze: Straßensegment + Verkehrsnetze: Straßensegment myroadlinklayerabstractger myroadlinklayerkeyword1 diff --git a/msautotest/wxs/expected/wms_inspire_scenario2_cap130.xml b/msautotest/wxs/expected/wms_inspire_scenario2_cap130.xml index 8a208b5080..71e8b1686a 100644 --- a/msautotest/wxs/expected/wms_inspire_scenario2_cap130.xml +++ b/msautotest/wxs/expected/wms_inspire_scenario2_cap130.xml @@ -29,8 +29,8 @@ conditions unknown None - 2048 - 2048 + 4096 + 4096 @@ -53,6 +53,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_inspire_scenario2_cap130_eng.xml b/msautotest/wxs/expected/wms_inspire_scenario2_cap130_eng.xml index 8a208b5080..71e8b1686a 100644 --- a/msautotest/wxs/expected/wms_inspire_scenario2_cap130_eng.xml +++ b/msautotest/wxs/expected/wms_inspire_scenario2_cap130_eng.xml @@ -29,8 +29,8 @@ conditions unknown None - 2048 - 2048 + 4096 + 4096 @@ -53,6 +53,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_inspire_scenario2_cap130_ger.xml b/msautotest/wxs/expected/wms_inspire_scenario2_cap130_ger.xml index e2f352dd67..6c61d131ea 100644 --- a/msautotest/wxs/expected/wms_inspire_scenario2_cap130_ger.xml +++ b/msautotest/wxs/expected/wms_inspire_scenario2_cap130_ger.xml @@ -29,8 +29,8 @@ conditions unknown None - 2048 - 2048 + 4096 + 4096 @@ -53,6 +53,7 @@ image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json @@ -108,7 +109,7 @@ TN.RoadTransportNetwork.RoadArea - Verkehrsnetze: Straßenfläche + Verkehrsnetze: Straßenfläche myroadareaabstractger myroadareakeyword1 @@ -139,7 +140,7 @@ TN.RoadTransportNetwork.RoadLink - Verkehrsnetze: Straßensegment + Verkehrsnetze: Straßensegment myroadlinklayerabstractger myroadlinklayerkeyword1 diff --git a/msautotest/wxs/expected/wms_north_polar_stereo_extent.xml b/msautotest/wxs/expected/wms_north_polar_stereo_extent.xml new file mode 100644 index 0000000000..5136d0958e --- /dev/null +++ b/msautotest/wxs/expected/wms_north_polar_stereo_extent.xml @@ -0,0 +1,143 @@ +Content-Type: text/xml; charset=UTF-8 + + + + + + WMS + Test simple wms + + ogc + wms + mapserver + + + + + Tom Kralidis + MapServer + + self + + postal +
123 SomeRoad Road
+ Toronto + Ontario + xxx-xxx + Canada +
+ +xx-xxx-xxx-xxxx + +xx-xxx-xxx-xxxx + tomkralidis@xxxxxxx.xxx +
+ None + None + 4096 + 4096 +
+ + + + + text/xml + + + + + + + + + image/png + image/jpeg + image/png; mode=8bit + application/x-pdf + image/svg+xml + image/tiff + application/vnd.google-earth.kml+xml + application/vnd.google-earth.kmz + application/json + + + + + + + + + text/plain + application/vnd.ogc.gml + + + + + + + + + text/xml + + + + + + + + + image/png + image/jpeg + image/png; mode=8bit + + + + + + + + + text/xml + + + + + + + + + + XML + INIMAGE + BLANK + + + + WMS_TEST + Test simple wms + WMS_TEST + + ogc + wms + mapserver + + EPSG:4326 + + -180 + 180 + -90 + 90 + + + + fake + fake + + -152.996 + -43.8099 + 27.6287 + 69.9699 + + + + +
diff --git a/msautotest/wxs/expected/wms_nosld_cap.xml b/msautotest/wxs/expected/wms_nosld_cap.xml index a5b99049c5..15fa4605d5 100644 --- a/msautotest/wxs/expected/wms_nosld_cap.xml +++ b/msautotest/wxs/expected/wms_nosld_cap.xml @@ -36,6 +36,7 @@ Content-Type: application/vnd.ogc.wms_xml; charset=UTF-8 image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_nosld_cap_postgis.xml b/msautotest/wxs/expected/wms_nosld_cap_postgis.xml index f6f4d96da0..6b683717d0 100644 --- a/msautotest/wxs/expected/wms_nosld_cap_postgis.xml +++ b/msautotest/wxs/expected/wms_nosld_cap_postgis.xml @@ -36,6 +36,7 @@ Content-Type: application/vnd.ogc.wms_xml; charset=UTF-8 image/tiff application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz + application/json diff --git a/msautotest/wxs/expected/wms_ogr_native.png b/msautotest/wxs/expected/wms_ogr_native.png new file mode 100644 index 0000000000..131905c697 Binary files /dev/null and b/msautotest/wxs/expected/wms_ogr_native.png differ diff --git a/msautotest/wxs/expected/wms_ogr_native_sql_data.png b/msautotest/wxs/expected/wms_ogr_native_sql_data.png new file mode 100644 index 0000000000..131905c697 Binary files /dev/null and b/msautotest/wxs/expected/wms_ogr_native_sql_data.png differ diff --git a/msautotest/wxs/expected/wms_polar_stereo.png b/msautotest/wxs/expected/wms_polar_stereo.png new file mode 100644 index 0000000000..94b81e0454 Binary files /dev/null and b/msautotest/wxs/expected/wms_polar_stereo.png differ diff --git a/msautotest/wxs/expected/wms_src_non_square_pixel_ticket5445.png b/msautotest/wxs/expected/wms_src_non_square_pixel_ticket5445.png new file mode 100644 index 0000000000..554f4b3710 Binary files /dev/null and b/msautotest/wxs/expected/wms_src_non_square_pixel_ticket5445.png differ diff --git a/msautotest/wxs/expected/wms_time_cap130.xml b/msautotest/wxs/expected/wms_time_cap130.xml index cf79553e3e..b891651250 100644 --- a/msautotest/wxs/expected/wms_time_cap130.xml +++ b/msautotest/wxs/expected/wms_time_cap130.xml @@ -10,8 +10,8 @@ Content-Type: text/xml; charset=UTF-8 none - 2048 - 2048 + 4096 + 4096 diff --git a/msautotest/wxs/expected/wms_time_cap130_postgis_postgis.xml b/msautotest/wxs/expected/wms_time_cap130_postgis_postgis.xml index cf79553e3e..b891651250 100644 --- a/msautotest/wxs/expected/wms_time_cap130_postgis_postgis.xml +++ b/msautotest/wxs/expected/wms_time_cap130_postgis_postgis.xml @@ -10,8 +10,8 @@ Content-Type: text/xml; charset=UTF-8 none - 2048 - 2048 + 4096 + 4096 diff --git a/msautotest/wxs/expected/wms_uvraster_lonwrap180_accross_hemisphere.png b/msautotest/wxs/expected/wms_uvraster_lonwrap180_accross_hemisphere.png new file mode 100644 index 0000000000..e34dc177dc Binary files /dev/null and b/msautotest/wxs/expected/wms_uvraster_lonwrap180_accross_hemisphere.png differ diff --git a/msautotest/wxs/expected/wms_uvraster_lonwrap180_east_hemisphere.png b/msautotest/wxs/expected/wms_uvraster_lonwrap180_east_hemisphere.png new file mode 100644 index 0000000000..05b1f814a6 Binary files /dev/null and b/msautotest/wxs/expected/wms_uvraster_lonwrap180_east_hemisphere.png differ diff --git a/msautotest/wxs/expected/wms_uvraster_lonwrap180_west_hemisphere.png b/msautotest/wxs/expected/wms_uvraster_lonwrap180_west_hemisphere.png new file mode 100644 index 0000000000..9ea25a0177 Binary files /dev/null and b/msautotest/wxs/expected/wms_uvraster_lonwrap180_west_hemisphere.png differ diff --git a/msautotest/wxs/expected/wms_uvraster_lonwrap180_whole_world.png b/msautotest/wxs/expected/wms_uvraster_lonwrap180_whole_world.png new file mode 100644 index 0000000000..21cd248b14 Binary files /dev/null and b/msautotest/wxs/expected/wms_uvraster_lonwrap180_whole_world.png differ diff --git a/msautotest/wxs/expected/wms_uvraster_map_reprojection_extent_intersecting_layer.png b/msautotest/wxs/expected/wms_uvraster_map_reprojection_extent_intersecting_layer.png new file mode 100644 index 0000000000..4b8d02422c Binary files /dev/null and b/msautotest/wxs/expected/wms_uvraster_map_reprojection_extent_intersecting_layer.png differ diff --git a/msautotest/wxs/expected/wms_uvraster_map_reprojection_extent_larger_than_layer.png b/msautotest/wxs/expected/wms_uvraster_map_reprojection_extent_larger_than_layer.png new file mode 100644 index 0000000000..d9c5ccfba3 Binary files /dev/null and b/msautotest/wxs/expected/wms_uvraster_map_reprojection_extent_larger_than_layer.png differ diff --git a/msautotest/wxs/expected/wms_uvraster_map_reprojection_extent_smaller_than_layer.png b/msautotest/wxs/expected/wms_uvraster_map_reprojection_extent_smaller_than_layer.png new file mode 100644 index 0000000000..f0b16e92e9 Binary files /dev/null and b/msautotest/wxs/expected/wms_uvraster_map_reprojection_extent_smaller_than_layer.png differ diff --git a/msautotest/wxs/ows_test_xml_escaping.map b/msautotest/wxs/ows_test_xml_escaping.map new file mode 100644 index 0000000000..3ef8a94d19 --- /dev/null +++ b/msautotest/wxs/ows_test_xml_escaping.map @@ -0,0 +1,109 @@ +# +# Test XML escaping +# +# REQUIRES: INPUT=GDAL OUTPUT=PNG SUPPORTS=WFS SUPPORTS=WMS +# +# Capabilities +# RUN_PARMS: wfs10_test_xml_escaping.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetCapabilities" > [RESULT_DEMIME_DEVERSION] +# RUN_PARMS: wfs11_test_xml_escaping.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.1.0&REQUEST=GetCapabilities" > [RESULT_DEMIME_DEVERSION] +# RUN_PARMS: wfs20_test_xml_escaping.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetCapabilities" > [RESULT_DEMIME_DEVERSION] +# RUN_PARMS: wms111_test_xml_escaping.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetCapabilities" > [RESULT_DEMIME_DEVERSION] +# RUN_PARMS: wms130_test_xml_escaping.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities" > [RESULT_DEMIME_DEVERSION] + +MAP + +NAME XML_ESCAPE_TEST +STATUS ON +SIZE 400 300 +#EXTENT 2018000 -73300 3410396 647400 +EXTENT -67.5725 42 -58.9275 48.5 +UNITS METERS +IMAGECOLOR 255 255 255 +SHAPEPATH ./data +SYMBOLSET etc/symbols.sym +FONTSET etc/fonts.txt + +# +# Start of web interface definition +# +WEB + + IMAGEPATH "/tmp/ms_tmp/" + IMAGEURL "/ms_tmp/" + + METADATA + "ows_updatesequence" "123" + "ows_title" "title & title" + "ows_onlineresource" "http://localhost/path/to/ows_test_xml_escaping?myparam=something&" + "ows_srs" "EPSG:4326 EPSG:4269" + "ows_abstract" "abstract&abstract" + "ows_keywordlist" "keyword&keyword" + "ows_service_onlineresource" "http://localhost" + "ows_fees" "fees&fees" + "ows_accessconstraints" "accessconstraints&accessconstraints" + "ows_addresstype" "addresstype&addresstype" + "ows_address" "address&address" + "ows_city" "city&city" + "ows_stateorprovince" "stateorprovince&stateorprovince" + "ows_postcode" "postcode&postcode" + "ows_country" "country&country" + "ows_contactelectronicmailaddress" "contactelectronicmailaddress&contactelectronicmailaddress" + "ows_contactvoicetelephone" "contactvoicetelephone&contactvoicetelephone" + "ows_contactfacsimiletelephone" "contactfacsimiletelephone&contactfacsimiletelephone" + "ows_contactperson" "contactperson&contactperson" + "ows_contactorganization" "contactorganization&contactorganization" + "ows_contactposition" "contactposition&contactposition" + "ows_hoursofservice" "hoursofservice&_hoursofservice" + "ows_contactinstructions" "contactinstructions&contactinstructions" + "ows_role" "role&role" + "ows_enable_request" "*" + END +END + +PROJECTION + "init=epsg:4326" +# "init=./data/epsg2:42304" +# "init=epsg:42304" +END + + +# +# Start of layer definitions +# + + + +LAYER + NAME province + DATA province + METADATA + "ows_title" "title&title" + "ows_description" "description&description" + "ows_abstract" "abstract&abstract" + "wfs_featureid" "NAME_E" + "wfs_metadataurl_href" "http://path/to/metadata_url" + "wfs_metadataurl_format" "text/xml" # WFS 1.1 only + "wfs_metadataurl_type" "FGDC" # WFS 1.1 only + "wfs_metadataurl_about" "about&about" # WFS 2.0 only + "gml_include_items" "NAME_E" + "gml_default_items" "" + END + TYPE POINT + STATUS ON + PROJECTION + "init=./data/epsg2:42304" +# "init=epsg:42304" + END + + DUMP TRUE + CLASSITEM "Name_e" + + CLASS + NAME "Province" + COLOR 200 255 0 + OUTLINECOLOR 120 120 120 + END +END # Layer + + +END # Map File diff --git a/msautotest/wxs/wcs_multi.map b/msautotest/wxs/wcs_multi.map index a220825dbf..4f34c4d71d 100644 --- a/msautotest/wxs/wcs_multi.map +++ b/msautotest/wxs/wcs_multi.map @@ -11,12 +11,12 @@ # RUN_PARMS: wcs_20_getcov_bands_name.dat [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi&FORMAT=image/tiff&mediatype=multipart/related&RANGESUBSET=Band9,Band5,Band1" > [RESULT_DEMIME] # # RUN_PARMS: wcs_20_getcov_bands_index_new.tif [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&RANGESUBSET=1,5,9" > [RESULT_DEMIME] -# RUN_PARMS: wcs_20_getcov_bands_name_new.tif [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&RANGESUBSET=Band9,Band5,Band1" > [RESULT_DEMIME] -# RUN_PARMS: wcs_20_getcov_bands_name_new.dat [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&mediatype=multipart/related&RANGESUBSET=Band9,Band5,Band1" > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_getcov_bands_name_new.tif [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&RANGESUBSET=myBand9,Band5,Band1" > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_getcov_bands_name_new.dat [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&mediatype=multipart/related&RANGESUBSET=myBand9,Band5,Band1" > [RESULT_DEMIME] # # RUN_PARMS: wcs_10_getcov_bands_name_new.dat [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=1.0.0&REQUEST=GetCoverage&COVERAGE=multi_new&FORMAT=GEOTIFF_8&BBOX=15,48,16,49&bands=9,5,1&CRS=EPSG:4326&WIDTH=5&HEIGHT=5" > [RESULT_DEMIME] # -# RUN_PARMS: wcs_20_getcov_bands_name_new_reproject.dat [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&mediatype=multipart/related&RANGESUBSET=Band9,Band5,Band1&OUTPUTCRS=EPSG:3857" > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_getcov_bands_name_new_reproject.dat [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&mediatype=multipart/related&RANGESUBSET=myBand9,Band5,Band1&OUTPUTCRS=EPSG:3857" > [RESULT_DEMIME] # # RUN_PARMS: wcs_20_getcov_native_format.tif [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new" > [RESULT_DEMIME] # @@ -26,8 +26,8 @@ # RUN_PARMS: wcs_20_post_bands_name.dat [MAPSERV] [POST]image/tiffmultimultipart/relatedBand9Band5Band1[/POST] > [RESULT_DEMIME] # # RUN_PARMS: wcs_20_post_bands_index_new.tif [MAPSERV] [POST]image/tiffmulti_new159[/POST] > [RESULT_DEMIME] -# RUN_PARMS: wcs_20_post_bands_name_new.tif [MAPSERV] [POST]image/tiffmulti_newBand9Band5Band1[/POST] > [RESULT_DEMIME] -# RUN_PARMS: wcs_20_post_bands_name_new.dat [MAPSERV] [POST]image/tiffmulti_newmultipart/relatedBand9Band5Band1[/POST] > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_post_bands_name_new.tif [MAPSERV] [POST]image/tiffmulti_newmyBand9Band5Band1[/POST] > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_post_bands_name_new.dat [MAPSERV] [POST]image/tiffmulti_newmultipart/relatedmyBand9Band5Band1[/POST] > [RESULT_DEMIME] # # Trim to 1px (#3857): # RUN_PARMS: wcs_20_multi_getcov_trim_y_to_1px.tif [MAPSERV] [POST]image/tiffmultiy1010.1imageCRS[/POST] > [RESULT_DEMIME] @@ -36,11 +36,35 @@ # # Updated API # +# RUN_PARMS: wcs_20_getcov_bands_single.tif [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&RANGESUBSET=Band2" > [RESULT_DEMIME] # RUN_PARMS: wcs_20_getcov_bands_interval.tif [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&RANGESUBSET=Band2:Band5" > [RESULT_DEMIME] -# RUN_PARMS: wcs_20_getcov_bands_intervals.tif [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&RANGESUBSET=Band2:Band5,Band7:Band9" > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_getcov_bands_intervals.tif [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&RANGESUBSET=Band2:Band5,Band7:myBand9" > [RESULT_DEMIME] # +# Using band indices +# +# RUN_PARMS: wcs_20_getcov_bands_single.tif [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&RANGESUBSET=2" > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_getcov_bands_interval.tif [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&RANGESUBSET=2:5" > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_getcov_bands_intervals.tif [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&RANGESUBSET=2:5,7:9" > [RESULT_DEMIME] +# +# Using default band names +# +# RUN_PARMS: wcs_20_getcov_bands_single.tif [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi_new&FORMAT=image/tiff&RANGESUBSET=band2" > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_getcov_bands_interval.tif [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi&FORMAT=image/tiff&RANGESUBSET=band2:band5" > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_getcov_bands_intervals.tif [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=multi&FORMAT=image/tiff&RANGESUBSET=band2:band5,band7:band9" > [RESULT_DEMIME] +# +# Updated API for POST/XML +# +# Using band names when supplied # # RUN_PARMS: wcs_20_post_bands_interval_component.tif [MAPSERV] [POST]image/tiffmulti_newBand1Band3Band8[/POST] > [RESULT_DEMIME] +# +# Using band indices +# +# RUN_PARMS: wcs_20_post_bands_interval_component.tif [MAPSERV] [POST]image/tiffmulti_new138[/POST] > [RESULT_DEMIME] +# +# Using default band names +# +# RUN_PARMS: wcs_20_post_bands_interval_component.tif [MAPSERV] [POST]image/tiffmultiband1band3band8[/POST] > [RESULT_DEMIME] MAP NAME TEST @@ -120,7 +144,7 @@ LAYER "wcs_imagemode" "BYTE" "wcs_bandcount" "9" - "wcs_rangeset_axes" "Band1 Band2 Band3 Band4 Band5 Band6 Band7 Band8 Band9" + "wcs_rangeset_axes" "bands" "wcs_rangeset_name" "Landsat 5 TM Bands" "wcs_rangeset_label" "Bands" "wcs_rangeset_description" "Bands for Landsat 5 TM" @@ -153,7 +177,8 @@ LAYER "wcs_imagemode" "BYTE" "wcs_bandcount" "9" - "wcs_band_names" "Band1 Band2 Band3 Band4 Band5 Band6 Band7 Band8 Band9" + "wcs_rangeset_axes" "bands" + "wcs_band_names" "Band1 Band2 Band3 Band4 Band5 Band6 Band7 Band8 myBand9" #default values "wcs_band_interpretation" "Default interpretation" @@ -175,4 +200,21 @@ LAYER END END + +LAYER + NAME multi_no_metadata + TYPE raster + STATUS ON + DUMP TRUE + + DATA data/multiband.tif + + PROJECTION + "init=epsg:4326" + END + METADATA + # as the name implies, no metadata + END +END + END diff --git a/msautotest/wxs/wcs_post.map b/msautotest/wxs/wcs_post.map index 5cd318d6a4..d2391373ac 100644 --- a/msautotest/wxs/wcs_post.map +++ b/msautotest/wxs/wcs_post.map @@ -93,10 +93,10 @@ # # # Scaling according to Scaling Extension -# RUN_PARMS: wcs_20_post_getcov_scaling_size_full.tif [MAPSERV] [POST]image/tiffgreyx10y20[/POST] > [RESULT_DEMIME] -# RUN_PARMS: wcs_20_getcov_scaling_scalefactor.tif [MAPSERV] [POST]image/tiffgrey1.5[/POST] > [RESULT_DEMIME] -# RUN_PARMS: wcs_20_getcov_scaling_scalefactor_per_axis.tif [MAPSERV] [POST]image/tiffgreyx1.5y2.0[/POST] > [RESULT_DEMIME] -# RUN_PARMS: wcs_20_getcov_scaling_extent.tif [MAPSERV] [POST]image/tiffgreyx1020y2030[/POST] > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_post_getcov_scaling_size_full.tif [MAPSERV] [POST]image/tiffgreyx10y20[/POST] > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_getcov_scaling_scalefactor.tif [MAPSERV] [POST]image/tiffgrey1.5[/POST] > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_getcov_scaling_scalefactor_per_axis.tif [MAPSERV] [POST]image/tiffgreyx1.5y2.0[/POST] > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_getcov_scaling_extent.tif [MAPSERV] [POST]image/tiffgreyx1020y2030[/POST] > [RESULT_DEMIME] # # Scaling in imageCRS # RUN_PARMS: wcs_20_post_getcov_imageCRS_scaling_size_trim_both.tif [MAPSERV] [POST]image/tiffgrey2030x1020y1030[/POST] > [RESULT_DEMIME] @@ -120,9 +120,9 @@ # RUN_PARMS: wcs_20_post_getcov_interpolation_bilinear.tif [MAPSERV] [POST]image/tiffgrey2020BILINEAR[/POST] > [RESULT_DEMIME] # # Interpolation according to Interpolation Extension -# RUN_PARMS: wcs_20_post_getcov_interpolation_nearest.tif [MAPSERV] [POST]image/tiffgreyx20y20NEAREST[/POST] > [RESULT_DEMIME] -# RUN_PARMS: wcs_20_post_getcov_interpolation_average.tif [MAPSERV] [POST]image/tiffgreyx20y20AVERAGE[/POST] > [RESULT_DEMIME] -# RUN_PARMS: wcs_20_post_getcov_interpolation_bilinear.tif [MAPSERV] [POST]image/tiffgreyx20y20BILINEAR[/POST] > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_post_getcov_interpolation_nearest.tif [MAPSERV] [POST]image/tiffgreyx20y20NEAREST[/POST] > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_post_getcov_interpolation_average.tif [MAPSERV] [POST]image/tiffgreyx20y20AVERAGE[/POST] > [RESULT_DEMIME] +# RUN_PARMS: wcs_20_post_getcov_interpolation_bilinear.tif [MAPSERV] [POST]image/tiffgreyx20y20BILINEAR[/POST] > [RESULT_DEMIME] # # GeoTIFF parameters # diff --git a/msautotest/wxs/wfs_200_allgeoms.map b/msautotest/wxs/wfs_200_allgeoms.map index 0ff350e10f..2e50b8260c 100644 --- a/msautotest/wxs/wfs_200_allgeoms.map +++ b/msautotest/wxs/wfs_200_allgeoms.map @@ -62,7 +62,7 @@ # RUN_PARMS: wfs_200_allgeoms_getfeaturebyid.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&STOREDQUERY_ID=urn:ogc:def:query:OGC-WFS::GetFeatureById&ID=point.1" > [RESULT_DEVERSION] # RUN_PARMS: wfs_200_allgeoms_exception_invalidquery.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&STOREDQUERY_ID=invalidquery" > [RESULT_DEVERSION] # RUN_PARMS: wfs_200_allgeoms_exception_myquery_missing_param.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&STOREDQUERY_ID=myquery" > [RESULT_DEVERSION] -# RUN_PARMS: wfs_200_allgeoms_myquery.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&STOREDQUERY_ID=myquery&LONGMIN=2&LATMIN=49&LONGMAX=2&LATMAX=49" > [RESULT_DEVERSION] +# RUN_PARMS: wfs_200_allgeoms_myquery.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&STOREDQUERY_ID=myquery&LONGMIN=1.99&LATMIN=48.99&LONGMAX=2.01&LATMAX=49.01" > [RESULT_DEVERSION] # RUN_PARMS: wfs_200_allgeoms_post_several_getfeaturebyid.xml [MAPSERV] [POST]point.1multipoint.1[/POST] > [RESULT_DEVERSION] # RUN_PARMS: wfs_200_allgeoms_post_exception_invalidquery.xml [MAPSERV] [POST][/POST] > [RESULT_DEVERSION] diff --git a/msautotest/wxs/wfs_combined_filter.map b/msautotest/wxs/wfs_combined_filter.map new file mode 100644 index 0000000000..4311014835 --- /dev/null +++ b/msautotest/wxs/wfs_combined_filter.map @@ -0,0 +1,90 @@ +# +# Test WFS +# +# REQUIRES: SUPPORTS=WFS INPUT=OGR + +# RUN_PARMS: wfs_combined_filter.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=road&FILTER=F_CODE67" > [RESULT] + +MAP + +NAME WFS_COMBINED_FILTER_TEST +STATUS ON +SIZE 400 300 +EXTENT -67.5725 42 -58.9275 48.5 +UNITS METERS +IMAGECOLOR 255 255 255 +SHAPEPATH ./data + +# +# Start of web interface definition +# +WEB + + IMAGEPATH "tmp/" + IMAGEURL "/ms_tmp/" + + METADATA + "ows_updatesequence" "123" + "wfs_title" "Test simple wfs" + "wfs_onlineresource" "http://localhost/path/to/wfs_simple?" +# "wfs_srs" "EPSG:4326 EPSG:4269 EPSG:3978 EPSG:27700" + "wms_title" "Test simple wms" + "wms_onlineresource" "http://localhost/path/to/wms_simple?" + "wms_srs" "EPSG:4269 EPSG:4326 EPSG:3978" + "ows_abstract" "Test WFS Abstract" + "ows_keywordlist" "ogc,wfs,gml,om" + "ows_service_onlineresource" "http://localhost" + "ows_fees" "none" + "ows_accessconstraints" "none" + "ows_addresstype" "postal" + "ows_address" "123 SomeRoad Road" + "ows_city" "Toronto" + "ows_stateorprovince" "Ontario" + "ows_postcode" "xxx-xxx" + "ows_country" "Canada" + "ows_contactelectronicmailaddress" "tomkralidis@xxxxxxx.xxx" + "ows_contactvoicetelephone" "+xx-xxx-xxx-xxxx" + "ows_contactfacsimiletelephone" "+xx-xxx-xxx-xxxx" + "ows_contactperson" "Tom Kralidis" + "ows_contactorganization" "MapServer" + "ows_contactposition" "self" + "ows_hoursofservice" "0800h - 1600h EST" + "ows_contactinstructions" "during hours of service" + "ows_role" "staff" + "wms_feature_info_mime_type" "text/csv" + "ows_enable_request" "*" + END +END + +PROJECTION + "+proj=latlong +datum=WGS84" +END + + +# +# Start of layer definitions +# + +LAYER + NAME road + DATA road + FILTER ([FNODE_] = 754) + METADATA + "ows_title" "road" + "ows_description" "road" + "wfs_featureid" "ROAD_ID" + "gml_include_items" "all" + "gml_exclude_items" "ROAD_" + "gml_types" "auto" + END + TYPE LINE + STATUS ON + PROJECTION + "init=epsg:3978" + END + + TEMPLATE "wfs_ogr.map" + DUMP TRUE +END # Layer + +END # Map File diff --git a/msautotest/wxs/wfs_filter.map b/msautotest/wxs/wfs_filter.map index 2abe7b315c..33c3561e6d 100644 --- a/msautotest/wxs/wfs_filter.map +++ b/msautotest/wxs/wfs_filter.map @@ -97,12 +97,16 @@ # Verify 3 AND # RUN_PARMS: wfs_filter_3_and.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=popplace&FILTER=NAMEDigbyNTS50021A12NTS50z021A12" > [RESULT] # + # Verify Not PropertyIsEqualTo # RUN_PARMS: wfs_filter_not_isequalto.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=popplace&FILTER=POP_RANGE4" > [RESULT] # # Verify BBOX Result: Digby # RUN_PARMS: wfs_filter_bbox.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=popplace&FILTER=POINT-65.86,44.56+-65.76,44.68" > [RESULT] # RUN_PARMS: wfs_filter_bbox_no_propertyname.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=popplace&FILTER=-65.86,44.56+-65.76,44.68" > [RESULT] + +# RUN_PARMS: wfs_filter_false_ogr_property_is_equal_and_bbox.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=popplace&FILTER=NAMExxxxxxxREG_CODE12POINT-65.86,44.56+-65.76,44.68" > [RESULT] + # # Verify BBOX Result with epsg in http://www.opengis.net/gml/srs/epsg.xml format: Digby # RUN_PARMS: wfs_filter_bbox_urlepsg.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&TYPENAME=popplace&FILTER=POINT272868.16,4938053.09+281261.3,4951109.39" > [RESULT] diff --git a/msautotest/wxs/wfs_filter_postgis.map b/msautotest/wxs/wfs_filter_postgis.map index 55027ac8cc..6818d7723c 100644 --- a/msautotest/wxs/wfs_filter_postgis.map +++ b/msautotest/wxs/wfs_filter_postgis.map @@ -11,6 +11,11 @@ # Verify PropertyIsEqualTo with no matching (due to case sensitivity) # RUN_PARMS: wfs_filter_postgis_property_is_equal_no_matching.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=popplace&FILTER=nameDIGBY" > [RESULT] # RUN_PARMS: wfs_filter_postgis_property_is_equal_case_insensitive.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=popplace&FILTER=nameDIGBY" > [RESULT] +# RUN_PARMS: wfs_filter_postgis_property_is_equal_empty.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=popplace&FILTER=name" > [RESULT] + +# RUN_PARMS: wfs_filter_postgis_property_is_null_zero_result.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&TYPENAME=popplace&FILTER=name&MAXFEATURES=1" > [RESULT] + +# RUN_PARMS: wfs_filter_postgis_property_is_null_result.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&TYPENAME=popplace&FILTER=name_e&MAXFEATURES=1" > [RESULT] # Test quotes in filter # RUN_PARMS: wfs_filter_postgis_property_is_equal_quote1.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=popplace&FILTER=name\"Tignish" > [RESULT] diff --git a/msautotest/wxs/wfs_ogr.map b/msautotest/wxs/wfs_ogr.map index 7674b0de61..e2795f22aa 100644 --- a/msautotest/wxs/wfs_ogr.map +++ b/msautotest/wxs/wfs_ogr.map @@ -63,6 +63,9 @@ # # Exception when requesting layers with different SRS # RUN_PARMS: wfsogr_exception_not_same_srs.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=multi,withnullvalues,popplace,road" > [RESULT] +# +# PropertyName and OGR output format (#5573) +# RUN_PARMS: wfsogr_ogroutput_propertyname.txt [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&TYPENAME=road&PROPERTYNAME=name_e&MAXFEATURES=1&OUTPUTFORMAT=multimidmif" > [RESULT] # # WMS 1.1 - GetFeatureInfo # diff --git a/msautotest/wxs/wfs_ogr_native_sql.map b/msautotest/wxs/wfs_ogr_native_sql.map new file mode 100644 index 0000000000..016cd0c449 --- /dev/null +++ b/msautotest/wxs/wfs_ogr_native_sql.map @@ -0,0 +1,333 @@ +# +# Test WFS +# +# REQUIRES: SUPPORTS=WFS INPUT=OGR +# +# simple bbox +# +# RUN_PARMS: wfs_ogr_native_sql_01.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry659159,4877386 696879,4898059" > [RESULT] + +# RUN_PARMS: wfs_ogr_native_sql_01_spatial_index_disabled.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns_spatial_index_disabled&OUTPUTFORMAT=GML2&FILTER=Geometry659159,4877386 696879,4898059" > [RESULT] + +# +# and, or, not +# +# RUN_PARMS: wfs_ogr_native_sql_02.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry643159,4877386 696879,4898059nameFanano" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_03.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry659159,4877386 696879,4898059nameFanano" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_04.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry659159,4877386 696879,4898059nameSambuca*" > [RESULT] +# +# = != > < >= <= with string +# +# RUN_PARMS: wfs_ogr_native_sql_05.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namefanano" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_06.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=nameFanano" > [RESULT] + +# RUN_PARMS: wfs_ogr_native_sql_06_disable_default_extent_for_getfeature.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns_disable_default_extent_for_getfeature&OUTPUTFORMAT=GML2&FILTER=nameFanano" > [RESULT] + +# RUN_PARMS: wfs_ogr_native_sql_07.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namefanano" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_08.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=nameFanano" > [RESULT] +# +# bug in MS filter: wfs_ogr_native_sql_09.xml should not have Fanano, matchCase="false" is ignored +# +# RUN_PARMS: wfs_ogr_native_sql_09.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namefanano" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_10.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namePistoia" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_11.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namePistoia" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_12.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namePistoia" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_13.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namePistoia" > [RESULT] +# +# = != > < >= <= with number +# +# RUN_PARMS: wfs_ogr_native_sql_14.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=peoples17502" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_15.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=peoples2000" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_16.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=peoples17502" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_17.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=peoples2000" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_18.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=peoples1604" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_19.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=peoples10002001" > [RESULT] +# +# missing comparison tests: time, boolean +# +# PropertyIsLike +# +# RUN_PARMS: wfs_ogr_native_sql_20.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=nameV*o" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_21.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namev*o" > [RESULT] +# +# bug in MS: ? is treated as * in this case: +# +# RUN_PARMS: wfs_ogr_native_sql_22.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=name?r*" > [RESULT] +# +# spatial predicates +# intersects, disjoint, touches, overlaps, crosses, within, contains, equals, beyond, dwithin +# +# RUN_PARMS: wfs_ogr_native_sql_23.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_24.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_25.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_26.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_27.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_28.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_29.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_30.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry662773 4891987.41" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_31.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=20000Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_32.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=1000Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# +# Same as wfs_ogr_native_sql_02 on a view +# RUN_PARMS: wfs_ogr_native_sql_33.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=myview&OUTPUTFORMAT=GML2&FILTER=Geometry643159,4877386 696879,4898059nameFanano" > [RESULT] +# +# Same as wfs_ogr_native_sql_02 on a "SELECT ... FROM " a table +# RUN_PARMS: wfs_ogr_native_sql_34.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns_select&OUTPUTFORMAT=GML2&FILTER=Geometry643159,4877386 696879,4898059nameFanano" > [RESULT] +# +# Same as wfs_ogr_native_sql_02 on a "SELECT ... FROM " a_view +# RUN_PARMS: wfs_ogr_native_sql_35.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=myview_select&OUTPUTFORMAT=GML2&FILTER=Geometry643159,4877386 696879,4898059nameFanano" > [RESULT] +# +# Same as wfs_ogr_native_sql_02 on a SELECT too complex to be edited, so falling back to client side evaluation +# RUN_PARMS: wfs_ogr_native_sql_36.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=select_too_complex_for_optim&OUTPUTFORMAT=GML2&FILTER=Geometry643159,4877386 696879,4898059nameFanano" > [RESULT] +# +# Test COUNT, STARTINDEX +# RUN_PARMS: wfs_ogr_native_sql_37.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAMES=towns&COUNT=1&STARTINDEX=2" > [RESULT_DEVERSION] +# RUN_PARMS: wfs_ogr_native_sql_38.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAMES=towns&COUNT=1&FILTER=nameGranaglione" > [RESULT_DEVERSION] +# +# Spatial query on a layer (unoptimized case with a 'SELECT ... FROM ... WHERE' DATA statement) that returns zero features +# RUN_PARMS: wfs_ogr_native_sql_39.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=select_zero_feature&OUTPUTFORMAT=GML2&FILTER=Geometry659159,4877386 696879,4898059" > [RESULT] +# +# PropertyIsNull +# RUN_PARMS: wfs_ogr_native_sql_40.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&TYPENAME=towns_with_null&FILTER=name" > [RESULT] + +# SortBy +# RUN_PARMS: wfs_ogr_native_sql_41.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAMES=towns&OUTPUTFORMAT=GML2&FILTER=nameFanano&SORTBY=name" > [RESULT_DEVERSION] + +# RUN_PARMS: wfs_ogr_native_sql_42.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAME=towns_disable_default_extent_for_getfeature&OUTPUTFORMAT=GML2&COUNT=1" > [RESULT_DEVERSION] +# RUN_PARMS: wfs_ogr_native_sql_43.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAME=towns_disable_default_extent_for_getfeature&OUTPUTFORMAT=GML2&COUNT=1&SRSNAME=EPSG:4326" > [RESULT_DEVERSION] + +MAP + +NAME WFS_OGR_NATIVE_SQL_TEST +STATUS ON +SIZE 400 300 +EXTENT 6 30 21 50 +UNITS METERS +IMAGECOLOR 255 255 255 + +# +# Start of web interface definition +# + +WEB + + IMAGEPATH "tmp/" + IMAGEURL "/ms_tmp/" + + METADATA + "wfs_title" "Test simple wfs" + "wfs_onlineresource" "http://localhost/path/to/wfs_simple?" + "wfs_srs" "EPSG:32632 EPSG:4326" + "wfs_enable_request" "*" + END +END + +PROJECTION + "+proj=latlong +datum=WGS84" +END + +# +# Start of layer definitions +# + +LAYER + NAME towns + DATA towns + CONNECTIONTYPE OGR + CONNECTION "./data/db.sqlite" + PROCESSING "NATIVE_SQL=YES" + METADATA + "ows_title" "towns" + "wfs_featureid" "ID" + "gml_include_items" "all" + "gml_types" "auto" + "wfs_getfeature_formatlist" "ogrgml" + END + TYPE POINT + STATUS ON + PROJECTION + "init=epsg:32632" + END + + TEMPLATE "wfs_ogr_native_sql.map" +END # Layer + +LAYER + NAME towns_disable_default_extent_for_getfeature + DATA towns + CONNECTIONTYPE OGR + CONNECTION "./data/db.sqlite" + PROCESSING "NATIVE_SQL=YES" + METADATA + "ows_title" "towns_disable_default_extent_for_getfeature" + "wfs_featureid" "ID" + "gml_include_items" "all" + "gml_types" "auto" + "wfs_getfeature_formatlist" "ogrgml" + "wfs_use_default_extent_for_getfeature" "no" + END + TYPE POINT + STATUS ON + PROJECTION + "init=epsg:32632" + END + + TEMPLATE "wfs_ogr_native_sql.map" +END # Layer + +LAYER + NAME towns_spatial_index_disabled + DATA towns + CONNECTIONTYPE OGR + CONNECTION "./data/db.sqlite" + PROCESSING "NATIVE_SQL=YES" + PROCESSING "USE_SPATIAL_INDEX=NO" + METADATA + "ows_title" "towns_spatial_index_disabled" + "wfs_featureid" "ID" + "gml_include_items" "all" + "gml_types" "auto" + "wfs_getfeature_formatlist" "ogrgml" + END + TYPE POINT + STATUS ON + PROJECTION + "init=epsg:32632" + END + + TEMPLATE "wfs_ogr_native_sql.map" +END # Layer + +LAYER + NAME towns_with_null + DATA towns_with_null + CONNECTIONTYPE OGR + CONNECTION "./data/db.sqlite" + PROCESSING "NATIVE_SQL=YES" + METADATA + "ows_title" "towns" + "wfs_featureid" "ID" + "gml_include_items" "all" + "gml_types" "auto" + "wfs_getfeature_formatlist" "ogrgml" + END + TYPE POINT + STATUS ON + PROJECTION + "init=epsg:32632" + END + + TEMPLATE "wfs_ogr_native_sql.map" +END # Layer + +LAYER + NAME towns_select + DATA "SELECT * FROM towns" + CONNECTIONTYPE OGR + CONNECTION "./data/db.sqlite" + PROCESSING "NATIVE_SQL=YES" + METADATA + "ows_title" "towns_select" + "wfs_featureid" "ID" + "gml_include_items" "all" + "gml_types" "auto" + "wfs_getfeature_formatlist" "ogrgml" + END + TYPE POINT + STATUS ON + PROJECTION + "init=epsg:32632" + END + + TEMPLATE "wfs_ogr_native_sql.map" +END # Layer + +LAYER + NAME myview + DATA myview + CONNECTIONTYPE OGR + CONNECTION "./data/db.sqlite" + PROCESSING "NATIVE_SQL=YES" + METADATA + "ows_title" "myview" + "wfs_featureid" "ID" + "gml_include_items" "all" + "gml_types" "auto" + "wfs_getfeature_formatlist" "ogrgml" + END + TYPE POINT + STATUS ON + PROJECTION + "init=epsg:32632" + END + + TEMPLATE "wfs_ogr_native_sql.map" +END # Layer + +LAYER + NAME myview_select + DATA "SELECT * FROM myview" + CONNECTIONTYPE OGR + CONNECTION "./data/db.sqlite" + PROCESSING "NATIVE_SQL=YES" + METADATA + "ows_title" "myview_select" + "wfs_featureid" "ID" + "gml_include_items" "all" + "gml_types" "auto" + "wfs_getfeature_formatlist" "ogrgml" + END + TYPE POINT + STATUS ON + PROJECTION + "init=epsg:32632" + END + + TEMPLATE "wfs_ogr_native_sql.map" +END # Layer + +LAYER + NAME select_too_complex_for_optim + DATA "SELECT * FROM towns WHERE 1" + CONNECTIONTYPE OGR + CONNECTION "./data/db.sqlite" + PROCESSING "NATIVE_SQL=YES" + METADATA + "ows_title" "select_too_complex_for_optim" + "wfs_featureid" "ID" + "gml_include_items" "all" + "gml_types" "auto" + "wfs_getfeature_formatlist" "ogrgml" + END + TYPE POINT + STATUS ON + PROJECTION + "init=epsg:32632" + END + + TEMPLATE "wfs_ogr_native_sql.map" +END # Layer + +LAYER + NAME select_zero_feature + DATA "SELECT * FROM towns WHERE 0" + CONNECTIONTYPE OGR + CONNECTION "./data/db.sqlite" + PROCESSING "NATIVE_SQL=YES" + METADATA + "ows_title" "select_zero_feature" + "wfs_featureid" "ID" + "gml_include_items" "all" + "gml_types" "auto" + "wfs_getfeature_formatlist" "ogrgml" + END + TYPE POINT + STATUS ON + PROJECTION + "init=epsg:32632" + END + + TEMPLATE "wfs_ogr_native_sql.map" +END # Layer + +END # Map File diff --git a/msautotest/wxs/wfs_ogr_no_native_sql.map b/msautotest/wxs/wfs_ogr_no_native_sql.map new file mode 100644 index 0000000000..cbf7ca83ab --- /dev/null +++ b/msautotest/wxs/wfs_ogr_no_native_sql.map @@ -0,0 +1,121 @@ +# +# Test WFS +# +# REQUIRES: SUPPORTS=WFS INPUT=OGR +# +# simple bbox +# +# RUN_PARMS: wfs_ogr_native_sql_01.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry659159,4877386 696879,4898059" > [RESULT] +# +# and, or, not +# +# RUN_PARMS: wfs_ogr_native_sql_02.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry643159,4877386 696879,4898059nameFanano" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_03.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry659159,4877386 696879,4898059nameFanano" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_04.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry659159,4877386 696879,4898059nameSambuca*" > [RESULT] +# +# = != > < >= <= with string +# +# RUN_PARMS: wfs_ogr_native_sql_05.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namefanano" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_06.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=nameFanano" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_07.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namefanano" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_08.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=nameFanano" > [RESULT] +# +# bug in MS filter: wfs_ogr_native_sql_09.xml should not have Fanano, matchCase="false" is ignored +# +# RUN_PARMS: wfs_ogr_native_sql_09.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namefanano" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_10.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namePistoia" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_11.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namePistoia" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_12.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namePistoia" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_13.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namePistoia" > [RESULT] +# +# = != > < >= <= with number +# +# RUN_PARMS: wfs_ogr_native_sql_14.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=peoples17502" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_15.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=peoples2000" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_16.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=peoples17502" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_17.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=peoples2000" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_18.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=peoples1604" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_19.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=peoples10002001" > [RESULT] +# +# missing comparison tests: time, boolean +# +# PropertyIsLike +# +# RUN_PARMS: wfs_ogr_native_sql_20.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=nameV*o" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_21.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=namev*o" > [RESULT] +# +# bug in MS: ? is treated as * in this case: +# +# UN_PARMS: wfs_ogr_native_sql_22.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=name?r*" > [RESULT] +# +# spatial predicates +# intersects, disjoint, touches, overlaps, crosses, within, contains, equals, beyond, dwithin +# +# RUN_PARMS: wfs_ogr_native_sql_23.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_24.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_25.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_26.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_27.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_28.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_29.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_30.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=Geometry662773 4891987.41" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_31.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=20000Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] +# RUN_PARMS: wfs_ogr_native_sql_32.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=1000Geometry653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103" > [RESULT] + +MAP + +NAME WFS_OGR_NATIVE_SQL_TEST +STATUS ON +SIZE 400 300 +EXTENT 6 30 21 50 +UNITS METERS +IMAGECOLOR 255 255 255 + +# +# Start of web interface definition +# + +WEB + + IMAGEPATH "tmp/" + IMAGEURL "/ms_tmp/" + + METADATA + "wfs_title" "Test simple wfs" + "wfs_onlineresource" "http://localhost/path/to/wfs_simple?" + "wfs_srs" "EPSG:32632" + "wfs_enable_request" "*" + END +END + +PROJECTION + "+proj=latlong +datum=WGS84" +END + +# +# Start of layer definitions +# + +LAYER + NAME towns + DATA towns + CONNECTIONTYPE OGR + CONNECTION "./data/db.sqlite" + PROCESSING "NATIVE_SQL=NO" + METADATA + "ows_title" "towns" + "wfs_featureid" "ID" + "gml_include_items" "all" + "gml_types" "auto" + "wfs_getfeature_formatlist" "ogrgml" + END + TYPE POINT + STATUS ON + PROJECTION + "init=epsg:32632" + END + + TEMPLATE "wfs_ogr_native_sql.map" +END # Layer + +END # Map File diff --git a/msautotest/wxs/wfs_ogr_tileindex_of_shp.map b/msautotest/wxs/wfs_ogr_tileindex_of_shp.map new file mode 100644 index 0000000000..57775a835e --- /dev/null +++ b/msautotest/wxs/wfs_ogr_tileindex_of_shp.map @@ -0,0 +1,86 @@ +# +# Test WFS : shapefile tileindex of shapefiles (#5291) +# +# REQUIRES: INPUT=OGR SUPPORTS=WFS +# +# In the logs, point_3_50.shp shouldn't appear +# RUN_PARMS: wfs_ogr_tileindex_of_shp_bbox_filter.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&REQUEST=GetFeature&SERVICE=WFS&TYPENAMES=ms:test&VERSION=2.0.0&FILTER=48.9 1.949.1 2.1" > [RESULT_DEVERSION] + +MAP + +NAME WFS_TEST +STATUS ON +SIZE 400 300 +EXTENT 1 48 4 51 +IMAGECOLOR 255 255 255 +SHAPEPATH "data" + +# +# Start of web interface definition +# +WEB + + IMAGEPATH "/tmp/ms_tmp/" + IMAGEURL "/ms_tmp/" + + METADATA + "ows_updatesequence" "123" + "wfs_title" "Test simple wfs" + "wfs_onlineresource" "http://localhost/path/to/wfs_simple?" + "wfs_srs" "EPSG:4326" + "ows_abstract" "Test WFS Abstract" + "ows_keywordlist" "ogc,wfs,gml,om" + "ows_service_onlineresource" "http://localhost" + "ows_fees" "none" + "ows_accessconstraints" "none" + "ows_addresstype" "postal" + "ows_address" "123 SomeRoad Road" + "ows_city" "Toronto" + "ows_stateorprovince" "Ontario" + "ows_postcode" "xxx-xxx" + "ows_country" "Canada" + "ows_contactelectronicmailaddress" "tomkralidis@xxxxxxx.xxx" + "ows_contactvoicetelephone" "+xx-xxx-xxx-xxxx" + "ows_contactfacsimiletelephone" "+xx-xxx-xxx-xxxx" + "ows_contactperson" "Tom Kralidis" + "ows_contactorganization" "MapServer" + "ows_contactposition" "self" + "ows_hoursofservice" "0800h - 1600h EST" + "ows_contactinstructions" "during hours of service" + "ows_role" "staff" + "ows_enable_request" "*" + END +END + +PROJECTION + "init=epsg:4326" +END + + +# +# Start of layer definitions +# + + +LAYER + NAME test + CONNECTIONTYPE OGR + TILEINDEX "shp_tileindex_of_shp.shp" + TILEITEM "LOCATION" + METADATA + "wfs_title" "test" + "wfs_description" "test" + "wfs_featureid" "id" + END + TYPE POINT + STATUS ON + EXTENT 1 48 4 51 + PROJECTION + "init=epsg:4326" + END + + DUMP TRUE +END # Layer + + +END # Map File diff --git a/msautotest/wxs/wfs_shape_tileindex_of_shp.map b/msautotest/wxs/wfs_shape_tileindex_of_shp.map new file mode 100644 index 0000000000..46378949fb --- /dev/null +++ b/msautotest/wxs/wfs_shape_tileindex_of_shp.map @@ -0,0 +1,85 @@ +# +# Test WFS : shapefile tileindex of shapefiles (#5291) +# +# REQUIRES: INPUT=OGR SUPPORTS=WFS +# +# In the logs, point_3_50.shp shouldn't appear +# RUN_PARMS: wfs_shape_tileindex_of_shp_bbox_filter.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&REQUEST=GetFeature&SERVICE=WFS&TYPENAMES=ms:test&VERSION=2.0.0&FILTER=48.9 1.949.1 2.1" > [RESULT_DEVERSION] + +MAP + +NAME WFS_TEST +STATUS ON +SIZE 400 300 +EXTENT 1 48 4 51 +IMAGECOLOR 255 255 255 +SHAPEPATH "data" + +# +# Start of web interface definition +# +WEB + + IMAGEPATH "/tmp/ms_tmp/" + IMAGEURL "/ms_tmp/" + + METADATA + "ows_updatesequence" "123" + "wfs_title" "Test simple wfs" + "wfs_onlineresource" "http://localhost/path/to/wfs_simple?" + "wfs_srs" "EPSG:4326" + "ows_abstract" "Test WFS Abstract" + "ows_keywordlist" "ogc,wfs,gml,om" + "ows_service_onlineresource" "http://localhost" + "ows_fees" "none" + "ows_accessconstraints" "none" + "ows_addresstype" "postal" + "ows_address" "123 SomeRoad Road" + "ows_city" "Toronto" + "ows_stateorprovince" "Ontario" + "ows_postcode" "xxx-xxx" + "ows_country" "Canada" + "ows_contactelectronicmailaddress" "tomkralidis@xxxxxxx.xxx" + "ows_contactvoicetelephone" "+xx-xxx-xxx-xxxx" + "ows_contactfacsimiletelephone" "+xx-xxx-xxx-xxxx" + "ows_contactperson" "Tom Kralidis" + "ows_contactorganization" "MapServer" + "ows_contactposition" "self" + "ows_hoursofservice" "0800h - 1600h EST" + "ows_contactinstructions" "during hours of service" + "ows_role" "staff" + "ows_enable_request" "*" + END +END + +PROJECTION + "init=epsg:4326" +END + + +# +# Start of layer definitions +# + + +LAYER + NAME test + TILEINDEX "shp_tileindex_of_shp.shp" + TILEITEM "LOCATION" + METADATA + "wfs_title" "test" + "wfs_description" "test" + "wfs_featureid" "id" + END + TYPE POINT + STATUS ON + EXTENT 1 48 4 51 + PROJECTION + "init=epsg:4326" + END + + DUMP TRUE +END # Layer + + +END # Map File diff --git a/msautotest/wxs/wfs_test5299.map b/msautotest/wxs/wfs_test5299.map new file mode 100644 index 0000000000..7f56958da8 --- /dev/null +++ b/msautotest/wxs/wfs_test5299.map @@ -0,0 +1,41 @@ +# +# Test fix for #5299 +# +# REQUIRES: SUPPORTS=WFS INPUT=OGR +# +# Generate dump to gml2 +# RUN_PARMS: wfs_test5299.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=test5299" > [RESULT] + +MAP + NAME test + EXTENT 0 0 10 10 + SIZE 200 200 + + PROJECTION + "init=epsg:4326" + END + + WEB + METADATA + OWS_ONLINERESOURCE "http://127.0.0.0.1" + OWS_SRS "EPSG:4326" + OWS_ENABLE_REQUEST "*" + END + END + + LAYER + NAME test5299 + TYPE POLYGON + STATUS ON + CONNECTIONTYPE OGR + CONNECTION "data/test5299.csv" + + METADATA + "ows_geomtype" "MultiPolygon" + END + + STYLEITEM "AUTO" + CLASS + END + END +END diff --git a/msautotest/wxs/wms_grid_reproj_to_3857.map b/msautotest/wxs/wms_grid_reproj_to_3857.map new file mode 100644 index 0000000000..0ae96122ba --- /dev/null +++ b/msautotest/wxs/wms_grid_reproj_to_3857.map @@ -0,0 +1,75 @@ +# +# Test WMS +# +# REQUIRES: INPUT=GDAL OUTPUT=PNG SUPPORTS=WMS +# +# Check that labels are in the left and right +# +# RUN_PARMS: wms_grid_reproj_to_3857_square_pixels_within_validity.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image/png&TRANSPARENT=false&LAYERS=grid4326&CRS=EPSG:3857&STYLES=&WIDTH=2000&HEIGHT=1500&BBOX=-20000000,-15000000,20000000,15000000" > [RESULT_DEMIME] +# +# RUN_PARMS: wms_grid_reproj_to_3857_square_pixels_beyond_validity.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image/png&TRANSPARENT=false&LAYERS=grid4326&CRS=EPSG:3857&STYLES=&WIDTH=2036&HEIGHT=739&BBOX=-39996745.16861447,-14460662.759102784,39683659.10075838,14460662.759102784" > [RESULT_DEMIME] +# +# RUN_PARMS: wms_grid_reproj_to_3857_non_square_pixels_beyond_validity.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image/png&TRANSPARENT=false&LAYERS=grid4326&CRS=EPSG:3857&STYLES=&WIDTH=2036&HEIGHT=735&BBOX=-39996745.16861447,-14460662.759102784,39683659.10075838,14460662.759102784" > [RESULT_DEMIME] +# + +MAP + NAME WMS_GRID_TEST + EXTENT -180 -90 180 90 + UNITS DD + FONTSET "../misc/fonts.lst" + + WEB + METADATA + wms_enable_request "*" + END + END + + PROJECTION + "init=epsg:4326" + END + + OUTPUTFORMAT + NAME GDPNG + DRIVER "GD/PNG" + MIMETYPE "image/png" + EXTENSION "png" + END + + LAYER + NAME "grid4326" + + METADATA + "wms_srs" "EPSG:4326 EPSG:3857" + "wms_extent" "-180 -90 180 90" + END + + TYPE LINE + + CLASS + NAME "Graticule" + COLOR 255 153 0 + LABEL + COLOR 0 0 0 + FONT lucida + TYPE truetype + SIZE 8 + POSITION AUTO + PARTIALS FALSE + BUFFER 5 + OUTLINECOLOR 255 255 255 + END + END + + PROJECTION + "init=epsg:4326" + END + + GRID + LABELFORMAT 'DDMMSS' # nice if a projected SRS used + MININTERVAL 30 + MAXINTERVAL 30 + END + + END # Layer + +END diff --git a/msautotest/wxs/wms_inspire_scenario1.map b/msautotest/wxs/wms_inspire_scenario1.map index 67cc48d0db..2bcdf05cfb 100644 --- a/msautotest/wxs/wms_inspire_scenario1.map +++ b/msautotest/wxs/wms_inspire_scenario1.map @@ -101,7 +101,7 @@ WEB "wms_contactorganization" "MapServer" #responsible organisation "wms_contactposition" "owner" #responsible organisation, value according "INSPIRE Metadata Regulation" (part D6) "wms_rootlayer_title.eng" "Transport networks: Road Area" - "wms_rootlayer_title.ger" "Verkehrsnetze: Straßenfläche" + "wms_rootlayer_title.ger" "Verkehrsnetze: Straßenfläche" "wms_rootlayer_abstract" "myroadarealayerabstract" #to test fallback "wms_rootlayer_abstract.ger" "myroadareaabstractger" "wms_rootlayer_keywordlist" "myroadareakeyword1,myroadareakeyword2" @@ -133,7 +133,7 @@ LAYER DATA "road_%language%" METADATA "wms_title.eng" "Transport networks: Road Link" - "wms_title.ger" "Verkehrsnetze: Straßensegment" + "wms_title.ger" "Verkehrsnetze: Straßensegment" "wms_abstract" "myroadlinklayerabstract" #to test fallback "wms_abstract.ger" "myroadlinklayerabstractger" "wms_keywordlist" "myroadlinklayerkeyword1,myroadlinklayerkeyword2" diff --git a/msautotest/wxs/wms_inspire_scenario2.map b/msautotest/wxs/wms_inspire_scenario2.map index 7ba5b99408..f891edb8ed 100644 --- a/msautotest/wxs/wms_inspire_scenario2.map +++ b/msautotest/wxs/wms_inspire_scenario2.map @@ -112,7 +112,7 @@ WEB "wms_contactorganization" "MapServer" #responsible organisation "wms_contactposition" "owner" #responsible organisation, value according "INSPIRE Metadata Regulation" (part D6) "wms_rootlayer_title.eng" "Transport networks: Road Area" - "wms_rootlayer_title.ger" "Verkehrsnetze: Straßenfläche" + "wms_rootlayer_title.ger" "Verkehrsnetze: Straßenfläche" "wms_rootlayer_abstract" "myroadarealayerabstract" #to test fallback "wms_rootlayer_abstract.ger" "myroadareaabstractger" "wms_rootlayer_keywordlist" "myroadareakeyword1,myroadareakeyword2" @@ -140,7 +140,7 @@ LAYER DATA "road_%language%" METADATA "wms_title.eng" "Transport networks: Road Link" - "wms_title.ger" "Verkehrsnetze: Straßensegment" + "wms_title.ger" "Verkehrsnetze: Straßensegment" "wms_abstract" "myroadlinklayerabstract" #to test fallback "wms_abstract.ger" "myroadlinklayerabstractger" "wms_keywordlist" "myroadlinklayerkeyword1,myroadlinklayerkeyword2" diff --git a/msautotest/wxs/wms_north_polar_stereo_extent.map b/msautotest/wxs/wms_north_polar_stereo_extent.map new file mode 100644 index 0000000000..44238f9e25 --- /dev/null +++ b/msautotest/wxs/wms_north_polar_stereo_extent.map @@ -0,0 +1,88 @@ +# +# Test WMS +# +# REQUIRES: INPUT=GDAL OUTPUT=PNG SUPPORTS=WMS +# +# +# Test Ex_GeographicBoundingBox in Capabilities +# RUN_PARMS: wms_north_polar_stereo_extent.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities" > [RESULT_DEVERSION] +# + +MAP + + NAME WMS_TEST + + EXTENT -180 -90 180 90 + SIZE 500 300 + PROJECTION + "init=epsg:4326" + END + +UNITS DD + +# +# Start of web interface definition +# +WEB + + IMAGEPATH "/tmp/ms_tmp/" + IMAGEURL "/ms_tmp/" + + METADATA + "wms_title" "Test simple wms" + "wms_onlineresource" "http://localhost/path/to/wms_simple?" + "wms_srs" "EPSG:4326" + "ows_schemas_location" "http://schemas.opengis.net" + "ows_keywordlist" "ogc,wms,mapserver" + "ows_service_onlineresource" "http://www.mapserver.org/" + "ows_fees" "None" + "ows_accessconstraints" "None" + "ows_addresstype" "postal" + "ows_address" "123 SomeRoad Road" + "ows_city" "Toronto" + "ows_stateorprovince" "Ontario" + "ows_postcode" "xxx-xxx" + "ows_country" "Canada" + "ows_contactelectronicmailaddress" "tomkralidis@xxxxxxx.xxx" + "ows_contactvoicetelephone" "+xx-xxx-xxx-xxxx" + "ows_contactfacsimiletelephone" "+xx-xxx-xxx-xxxx" + "ows_contactperson" "Tom Kralidis" + "ows_contactorganization" "MapServer" + "ows_contactposition" "self" + + "ows_enable_request" "*" + END +END + +# +# Start of layer definitions +# + +LAYER + NAME fake + DATA fake + TEMPLATE "ttt" + METADATA + "wms_title" "fake" + "wms_description" "fake" + "ows_extent" "-2099127.494 -5739388.521 4340872.506 -2099388.521" + END + TYPE LINE + STATUS ON + PROJECTION + "proj=stere" + "lat_0=90" + "lat_ts=60" + "lon_0=252" + "k=90" + "x_0=0" + "y_0=0" + "a=6371229" + "b=6371229" + "units=m" + "no_defs" + END + +END # Layer + +END # Map File diff --git a/msautotest/wxs/wms_ogr_native_sql.map b/msautotest/wxs/wms_ogr_native_sql.map new file mode 100644 index 0000000000..9703d02b8a --- /dev/null +++ b/msautotest/wxs/wms_ogr_native_sql.map @@ -0,0 +1,85 @@ +# +# Test WMS +# +# REQUIRES: SUPPORTS=WMS INPUT=OGR +# +# simple bbox +# +# RUN_PARMS: wms_ogr_native.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.1.0&REQUEST=GetMap&TYPENAME=towns&FORMAT=image/png&BBOX=659159,4877386,696879,4898059&LAYERS=towns&WIDTH=100&HEIGHT=100&SRS=EPSG:32632" > [RESULT_DEMIME] +# RUN_PARMS: wms_ogr_native_sql_data.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.1.0&REQUEST=GetMap&TYPENAME=towns_sql&FORMAT=image/png&BBOX=659159,4877386,696879,4898059&LAYERS=towns_sql&WIDTH=100&HEIGHT=100&SRS=EPSG:32632" > [RESULT_DEMIME] + +MAP + +NAME WMS_OGR_NATIVE_SQL_TEST +STATUS ON +SIZE 400 300 +EXTENT 6 30 21 50 +UNITS METERS +IMAGECOLOR 255 255 255 + +# +# Start of web interface definition +# + +WEB + + IMAGEPATH "tmp/" + IMAGEURL "/ms_tmp/" + + METADATA + "wms_title" "Test simple wms" + "wms_onlineresource" "http://localhost/path/to/wms_simple?" + "wms_srs" "EPSG:32632" + "wms_enable_request" "*" + END +END + +PROJECTION + "+proj=latlong +datum=WGS84" +END + +# +# Start of layer definitions +# + +LAYER + NAME towns + DATA towns + CONNECTIONTYPE OGR + CONNECTION "./data/db.sqlite" + PROCESSING "NATIVE_SQL=YES" + TYPE POINT + STATUS ON + PROJECTION + "init=epsg:32632" + END + CLASS + TEXT '[peoples]' + LABEL + END + END + + TEMPLATE "foo" +END # Layer + +LAYER + NAME towns_sql + DATA "SELECT county, geometry, peoples FROM towns" + CONNECTIONTYPE OGR + CONNECTION "./data/db.sqlite" + PROCESSING "NATIVE_SQL=YES" + TYPE POINT + STATUS ON + PROJECTION + "init=epsg:32632" + END + CLASS + TEXT '[peoples]' + LABEL + END + END + + TEMPLATE "foo" +END # Layer + +END # Map File diff --git a/msautotest/wxs/wms_polar_stereo.map b/msautotest/wxs/wms_polar_stereo.map new file mode 100644 index 0000000000..5f3cd11d54 --- /dev/null +++ b/msautotest/wxs/wms_polar_stereo.map @@ -0,0 +1,48 @@ +# +# Tests support for images in polar stereographic projection +# +# REQUIRES: SUPPORTS=WMS +# +# +# GetMap +# RUN_PARMS: wms_polar_stereo.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&LAYERS=test&STYLES=&CRS=EPSG:4326&BBOX=-89,-180,90,180&WIDTH=200&HEIGHT=200&FORMAT=image/png" > [RESULT_DEMIME] + +MAP + +NAME TEST +STATUS ON +SIZE 200 200 +EXTENT -180 -89 180 90 +IMAGECOLOR 0 0 0 + +PROJECTION + "init=epsg:4326" +END + +IMAGETYPE png8_t + +OUTPUTFORMAT + NAME png8_t + DRIVER "GD/PNG" + IMAGEMODE PC256 + TRANSPARENT OFF +END + +WEB + METADATA + "ows_enable_request" "*" + "wms_srs" "EPSG:4326" + END +END + +LAYER + NAME test + TYPE raster + STATUS default + DATA data/polar_stereo.tif + PROJECTION + AUTO + END +END +END # of map file + diff --git a/msautotest/wxs/wms_src_non_square_pixel_ticket5445.map b/msautotest/wxs/wms_src_non_square_pixel_ticket5445.map new file mode 100644 index 0000000000..40a18bcf06 --- /dev/null +++ b/msautotest/wxs/wms_src_non_square_pixel_ticket5445.map @@ -0,0 +1,85 @@ +# +# Test WMS +# +# REQUIRES: INPUT=GDAL OUTPUT=PNG SUPPORTS=WMS +# +# RUN_PARMS: wms_src_non_square_pixel_ticket5445.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&BBOX=-7.21916,48.40401621621622,-3.4696399999999996,50.43078378378378&SERVICE=WMS&REQUEST=GetMap&FORMAT=image/png&styles=&layers=continent&width=1000&height=541&srs=EPSG:4326&EXCEPTIONS=application/vnd.ogc.se_inimage&TRANSPARENT=TRUE&VERSION=1.1.1" > [RESULT_DEMIME] + + +MAP + +NAME WMS_TEST +STATUS ON +SIZE 400 300 +UNITS DD +IMAGECOLOR 255 255 255 +SHAPEPATH ./data + +EXTENT -803633.215155169 6142218.69849575 -386238.558035974 6488409.59450128 +PROJECTION + "init=epsg:3395" +END + +OUTPUTFORMAT + NAME GDPNG + DRIVER "GD/PNG" + MIMETYPE "image/png" + EXTENSION "png" +END + +# +# Start of web interface definition +# +WEB + + IMAGEPATH "/tmp/ms_tmp/" + IMAGEURL "/ms_tmp/" + + METADATA + "ows_updatesequence" "123" + "wms_title" "Test simple wms" + "wms_onlineresource" "http://localhost/path/to/wms_simple?" + "wms_srs" "EPSG:42304 EPSG:42101 EPSG:4269 EPSG:4326" + "ows_schemas_location" "http://schemas.opengis.net" + "ows_keywordlist" "ogc,wms,mapserver" + "ows_service_onlineresource" "http://www.mapserver.org/" + "ows_fees" "None" + "ows_accessconstraints" "None" + "ows_addresstype" "postal" + "ows_address" "123 SomeRoad Road" + "ows_city" "Toronto" + "ows_stateorprovince" "Ontario" + "ows_postcode" "xxx-xxx" + "ows_country" "Canada" + "ows_contactelectronicmailaddress" "tomkralidis@xxxxxxx.xxx" + "ows_contactvoicetelephone" "+xx-xxx-xxx-xxxx" + "ows_contactfacsimiletelephone" "+xx-xxx-xxx-xxxx" + "ows_contactperson" "Tom Kralidis" + "ows_contactorganization" "MapServer" + "ows_contactposition" "self" + + "ows_rootlayer_title" "My Layers" + "ows_rootlayer_abstract" "These are my layers" + "ows_rootlayer_keywordlist" "layers,list" + "ows_layerlimit" "1" + "ows_enable_request" "*" + "wms_getmap_formatlist" "image/png,image/png; mode=24bit,image/jpeg,image/gif,image/png; mode=8bit,image/tiff" + END +END + + +# +# Start of layer definitions +# + +LAYER + NAME "continent" + PROJECTION + "init=epsg:3395" + END + TYPE RASTER + + DATA "ticket5445.tif" +END + +END # Map File diff --git a/msautotest/wxs/wms_uvraster_lonwrap180.map b/msautotest/wxs/wms_uvraster_lonwrap180.map new file mode 100644 index 0000000000..9f278ee8e0 --- /dev/null +++ b/msautotest/wxs/wms_uvraster_lonwrap180.map @@ -0,0 +1,74 @@ +# +# Test WMS +# +# REQUIRES: INPUT=GDAL OUTPUT=PNG SUPPORTS=WMS +# +# RUN_PARMS: wms_uvraster_lonwrap180_whole_world.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=-90,-180,90,180&CRS=EPSG:4326&WIDTH=744&HEIGHT=372&LAYERS=test&STYLES=&FORMAT=image/png&DPI=120&MAP_RESOLUTION=120&TRANSPARENT=TRUE" > [RESULT_DEMIME] +# +# RUN_PARMS: wms_uvraster_lonwrap180_west_hemisphere.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=-90,-180,90,0&CRS=EPSG:4326&WIDTH=372&HEIGHT=372&LAYERS=test&STYLES=&FORMAT=image/png&DPI=120&MAP_RESOLUTION=120&TRANSPARENT=TRUE" > [RESULT_DEMIME] +# +# RUN_PARMS: wms_uvraster_lonwrap180_east_hemisphere.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=-90,0,90,180&CRS=EPSG:4326&WIDTH=372&HEIGHT=372&LAYERS=test&STYLES=&FORMAT=image/png&DPI=120&MAP_RESOLUTION=120&TRANSPARENT=TRUE" > [RESULT_DEMIME] +# +# RUN_PARMS: wms_uvraster_lonwrap180_accross_hemisphere.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=-90,-90,90,90&CRS=EPSG:4326&WIDTH=372&HEIGHT=372&LAYERS=test&STYLES=&FORMAT=image/png&DPI=120&MAP_RESOLUTION=120&TRANSPARENT=TRUE" > [RESULT_DEMIME] + +MAP + NAME uvraster_lonwrap + EXTENT -180 -90 180 90 + MAXSIZE 4096 + SIZE 500 300 + SHAPEPATH ./data + + PROJECTION + "init=epsg:4326" + END + + SYMBOL + NAME "arrow" + FILLED TRUE + POINTS + 1.2 0 + 1.2 6 + 3 6 + 0 10 + -3 6 + -1.2 6 + -1.2 0 + 1.2 0 + END + END + + WEB + METADATA + "ows_enable_request" "*" + END + END + + LAYER + DATA "uvraster_lonwrap180.tif" + NAME "test" + TYPE POINT + CONNECTIONTYPE uvraster + + EXTENT 0 -80.1 360 89.9 + + PROCESSING "BANDS=1,2" + PROCESSING "UV_SPACING=17" + + PROJECTION + "proj=longlat" + "a=6371229" + "b=6371229" + "lon_wrap=180" + END + + CLASS + STYLE + SYMBOL "arrow" + COLOR 255 0 0 + ANGLE [uv_angle] + SIZE 10 + END + END + + END +END diff --git a/msautotest/wxs/wms_uvraster_map_reprojection.map b/msautotest/wxs/wms_uvraster_map_reprojection.map new file mode 100644 index 0000000000..1a06a57848 --- /dev/null +++ b/msautotest/wxs/wms_uvraster_map_reprojection.map @@ -0,0 +1,77 @@ +# +# Test WMS +# +# REQUIRES: INPUT=GDAL OUTPUT=PNG SUPPORTS=WMS +# +# RUN_PARMS: wms_uvraster_map_reprojection_extent_larger_than_layer.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=-85,-500,190,200&CRS=EPSG:4326&WIDTH=946&HEIGHT=583&LAYERS=test&STYLES=&FORMAT=image/png&DPI=98&MAP_RESOLUTION=98&FORMAT_OPTIONS=dpi:98&TRANSPARENT=TRUE" > [RESULT_DEMIME] +# +# RUN_PARMS: wms_uvraster_map_reprojection_extent_smaller_than_layer.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=30,-170,60,-100&CRS=EPSG:4326&WIDTH=400&HEIGHT=200&LAYERS=test&STYLES=&FORMAT=image/png&TRANSPARENT=TRUE" > [RESULT_DEMIME] +# +# RUN_PARMS: wms_uvraster_map_reprojection_extent_intersecting_layer.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=30,-200,60,-100&CRS=EPSG:4326&WIDTH=400&HEIGHT=200&LAYERS=test&STYLES=&FORMAT=image/png&TRANSPARENT=TRUE" > [RESULT_DEMIME] + +MAP + NAME test + EXTENT -180 -90 180 90 + MAXSIZE 4096 + SIZE 500 300 + SHAPEPATH ./data + + SYMBOL + NAME "arrow_wind" + TYPE vector + FILLED true + POINTS + 0 1.2 + 6 1.2 + 6 3 + 10 0 + 6 -3 + 6 -1.2 + 0 -1.2 + 0 1.2 + END + END + + PROJECTION + "init=epsg:4326" + END + + WEB + METADATA + "ows_enable_request" "*" + END + END + + LAYER + NAME "test" + TYPE POINT + CONNECTIONTYPE uvraster + PROCESSING "BANDS=1,2" + PROCESSING "UV_SPACING=20" + + PROJECTION + "proj=stere" + "lat_0=90" + "lat_ts=60" + "lon_0=249" + "k=90" + "x_0=0" + "y_0=0" + "a=6371229" + "b=6371229" + "units=m" + "no_defs" + END + + DATA 'wms_uvraster_map_reprojection.tif' + + CLASS + STYLE + COLOR 0 0 127 + SYMBOL "arrow_wind" + ANGLE [uv_angle] + SIZE 12 + END + END + END +END