[gdal] 03/08: Imported Upstream version 2.1.3~rc1+dfsg

Bas Couwenberg sebastic at debian.org
Fri Jan 20 10:25:54 UTC 2017


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

sebastic pushed a commit to branch experimental-2.1
in repository gdal.

commit 974e4c877ae023118a716aa47b36defb50e7bac2
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Fri Jan 20 10:19:18 2017 +0100

    Imported Upstream version 2.1.3~rc1+dfsg
---
 GDALmake.opt.in                                    |   2 +-
 NEWS                                               | 119 +++++++
 VERSION                                            |   2 +-
 alg/gdalrasterize.cpp                              |  53 ++-
 alg/gdaltransformer.cpp                            |   8 +-
 alg/gdalwarpkernel.cpp                             |  29 +-
 alg/gdalwarpkernel_opencl.c                        |   9 +-
 apps/gdal_rasterize_lib.cpp                        |   9 +-
 apps/gdalinfo_lib.cpp                              |   8 +-
 configure                                          |  25 +-
 configure.in                                       |   3 +-
 frmts/adrg/adrgdataset.cpp                         |  72 +++-
 frmts/dods/dodsdataset2.cpp                        |  12 +-
 frmts/grass/pkg/Makefile.in                        |  13 -
 frmts/grass/pkg/configure                          |  70 +++-
 frmts/grass/pkg/configure.in                       |  15 +-
 frmts/gtiff/geotiff.cpp                            |  17 +-
 frmts/hdf4/hdf4dataset.cpp                         |   5 +-
 frmts/idrisi/IdrisiDataset.cpp                     |  10 +-
 frmts/netcdf/netcdfdataset.cpp                     |  30 +-
 frmts/openjpeg/openjpegdataset.cpp                 |  18 +-
 frmts/pcidsk/pcidskdataset2.cpp                    |  63 +++-
 frmts/pcidsk/sdk/segment/metadatasegment_p.cpp     |  18 +-
 frmts/rmf/rmfdataset.cpp                           |  22 +-
 frmts/sentinel2/frmt_sentinel2.html                |   6 +-
 frmts/sentinel2/sentinel2dataset.cpp               | 322 ++++++++++++++---
 frmts/vrt/vrtsources.cpp                           |  14 +-
 gcore/gdal_version.h                               |   6 +-
 makefile.vc                                        |  10 +-
 makegdal_gen.bat                                   | 381 ++++++++++++++-------
 man/man1/gdal-config.1                             |   2 +-
 man/man1/gdal2tiles.1                              |   2 +-
 man/man1/gdal_calc.1                               |   2 +-
 man/man1/gdal_contour.1                            |   2 +-
 man/man1/gdal_edit.1                               |   2 +-
 man/man1/gdal_fillnodata.1                         |   2 +-
 man/man1/gdal_grid.1                               |   2 +-
 man/man1/gdal_merge.1                              |   2 +-
 man/man1/gdal_pansharpen.1                         |   2 +-
 man/man1/gdal_polygonize.1                         |   2 +-
 man/man1/gdal_proximity.1                          |   2 +-
 man/man1/gdal_rasterize.1                          |   2 +-
 man/man1/gdal_retile.1                             |   2 +-
 man/man1/gdal_sieve.1                              |   2 +-
 man/man1/gdal_translate.1                          |   2 +-
 man/man1/gdal_utilities.1                          |   2 +-
 man/man1/gdaladdo.1                                |   2 +-
 man/man1/gdalbuildvrt.1                            |   2 +-
 man/man1/gdalcompare.1                             |   2 +-
 man/man1/gdaldem.1                                 |   2 +-
 man/man1/gdalinfo.1                                |   2 +-
 man/man1/gdallocationinfo.1                        |   2 +-
 man/man1/gdalmanage.1                              |   2 +-
 man/man1/gdalmove.1                                |   2 +-
 man/man1/gdalsrsinfo.1                             |   2 +-
 man/man1/gdaltindex.1                              |   2 +-
 man/man1/gdaltransform.1                           |   2 +-
 man/man1/gdalwarp.1                                |   2 +-
 man/man1/gnm_utilities.1                           |   2 +-
 man/man1/gnmanalyse.1                              |   2 +-
 man/man1/gnmmanage.1                               |   2 +-
 man/man1/nearblack.1                               |   2 +-
 man/man1/ogr2ogr.1                                 |   2 +-
 man/man1/ogr_utilities.1                           |   2 +-
 man/man1/ogrinfo.1                                 |   2 +-
 man/man1/ogrlineref.1                              |   2 +-
 man/man1/ogrtindex.1                               |   2 +-
 man/man1/pct2rgb.1                                 |   2 +-
 man/man1/rgb2pct.1                                 |   2 +-
 nmake.opt                                          |   7 +-
 ogr/gml2ogrgeometry.cpp                            |  10 +-
 ogr/ogrct.cpp                                      |  42 ++-
 ogr/ogrgeometryfactory.cpp                         |   6 +-
 .../amigocloud/ogramigoclouddatasource.cpp         |   5 +
 ogr/ogrsf_frmts/amigocloud/ogramigocloudlayer.cpp  |   7 +-
 .../amigocloud/ogramigocloudtablelayer.cpp         |   9 +
 ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp      |  27 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h         |   4 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp   |   4 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp   |   2 +
 ogr/ogrsf_frmts/ili/ogr_ili1.h                     |   4 +-
 ogr/ogrsf_frmts/ili/ogrili1layer.cpp               | 260 +++++++++++---
 ogr/ogrsf_frmts/makefile.vc                        |  15 +-
 ogr/ogrsf_frmts/mssqlspatial/makefile.vc           |  32 +-
 .../mssqlspatial/ogrmssqlspatialdriver.cpp         |  10 +-
 ogr/ogrsf_frmts/nas/nasreader.cpp                  |   3 +-
 ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp           |  10 +-
 ogr/ogrsf_frmts/sde/ogrsdedriver.cpp               |   6 +-
 ogr/ogrsf_frmts/shape/shpopen.c                    |  13 +-
 ogr/ogrsf_frmts/sqlite/ogr_sqlite.h                |   8 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp     | 120 ++++++-
 ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp          |  22 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp    |   6 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp     |  11 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp      |  10 +-
 ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp                |  13 +-
 ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp         |  25 +-
 port/cpl_config.h.in                               |   3 +
 port/cpl_http.cpp                                  |  23 +-
 port/cpl_vsil_unix_stdio_64.cpp                    |  16 +-
 swig/include/perl/gdal_perl.i                      |   4 +-
 swig/include/perl/ogr_perl.i                       |   6 +-
 swig/include/python/gdal_python.i                  |   8 +-
 swig/perl/lib/Geo/GDAL.pm                          |   4 +-
 swig/perl/lib/Geo/OGR.pm                           |   6 +-
 swig/perl/t/geom.t                                 |  60 ++++
 swig/python/osgeo/gdal.py                          |   6 +-
 swig/python/scripts/gdal_calc.py                   |   2 +-
 swig/python/setup.py                               |  15 +-
 109 files changed, 1776 insertions(+), 517 deletions(-)

diff --git a/GDALmake.opt.in b/GDALmake.opt.in
index 4a05588..3d104c5 100644
--- a/GDALmake.opt.in
+++ b/GDALmake.opt.in
@@ -121,7 +121,7 @@ GDAL_INCLUDE	=	-I$(GDAL_ROOT)/port -I$(GDAL_ROOT)/gcore \
 # libtool targets and help variables
 LIBGDAL	:=		libgdal.la
 LIBGDAL_CURRENT	:=	21
-LIBGDAL_REVISION	:=	2
+LIBGDAL_REVISION	:=	3
 LIBGDAL_AGE	:=	1
 
 # native build targets and variables
diff --git a/NEWS b/NEWS
index 976cf9e..48e49fe 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,122 @@
+= GDAL/OGR 2.1.3 Release Notes = 
+
+The 2.1.3 release is a bug fix release.
+
+== Build ==
+
+* Windows: include plugins in clean, oci: also clean dll
+* windows: makegdal_gen.bat: update script to generate most recent Visual C++ project files (#6635)
+
+== Port ==
+
+* CPLHTTPFetch(): add a CAINFO option to set the path to the CA bundle file. As a fallback also honour the CURL_CA_BUNDLE and SSL_CERT_FILE environment variables used by the curl binary, which makes this setting also available for /vsicurl/, /vsicurl_streaming/, /vsis3/ and /vsis3_streaming/ file systems (#6732)
+* Fix GetDiskFreeSpace() on 32bit Linux to avoid 32bit overflow when free disk space is above 4 GB (#6750)
+
+== GDAL algorithms ==
+
+* Warper: avoid undefined behaviour when doing floating point to int conversion, that may trigger exception with some compilers (LLVM 8) (#6753)
+* OpenCL wrapper: do not use CL_MEM_COPY_HOST_PTR flag as it is forbidden by the opencl spec for clGetSupportedImageFormats() use case. Fix for NVidia use case (#6624)
+* OpenCL wrapper: fix wrapping of Float32 data type with NVIDIA OpenCL (#6669)
+
+== Utilities ==
+
+* gdalinfo -json: fix order of points in wgs84Extent.coordinates (github #166)
+* gdal_rasterize: fix segfaults when rasterizing into an ungeoreferenced raster, or when doing 'gdal_rasterize my.shp my.tif' with a non existing my.tif (#6738)
+* gdal_calc.py: fix usage message
+
+== GDAL drivers ==
+
+ADRG driver:
+* handle north and south polar zones (ZNA 9 and 18) (#6783)
+
+DODS driver:
+* fix crash on URL that are not DODS servers (#6718)
+
+HDF4 driver:
+* include hdf4compat.h in hdf4dataset.cpp
+
+GRASS driver:
+* frmts/grass/pkg/configure: add support for GRASS 7.2 (#6785)
+* frmts/grass/pkg/Makefile.in: do not clone datum tables and drivers (#2953)
+
+GTiff driver:
+* fix creating an image with the Create() interface with BLOCKYSIZE > image height (#6743)
+* don't check free disk space when outputting to /vsistdout/ (#6768)
+
+Idrisi/RST driver:
+* on creation: use geotransform of source dataset even if it doesn't have a SRS (#6727)
+
+netCDF driver:
+* fix erroneous detection of a non-longitude X axis as a longitude axis that caused a shift of 360m on the georeferencing (#6759)
+
+OpenJPEG driver:
+* for single-line organized images, such as found in some GRIB2 JPEG2000 images, use a Wx1 block size to avoid huge performance issues (#6719)
+
+PCIDSK driver:
+* handle Exceptions returned from destructor and check access rights in setters (github #183)
+
+RMF driver:
+* fix reading nodata for non-double data type (github #174)
+
+Sentinel2 driver:
+* add support for new "Safe Compact" encoding of L1C products (#6745)
+
+VRT driver:
+* Fix linking error on VRTComplexSource::RasterIOInternal<float>() (#6748)
+
+== OGR core ==
+
+* GML geometry parsing: avoid 'Cannot add a compound curve inside a compound curve' error (#6777)
+* Avoid assertion when stroking degenerated arcs (#6778)
+* Coordinate transformation: prevent unnecessary coordinate transformations (github #184)
+
+== OGR drivers == 
+
+AmigoCloud driver:
+* add option to receive an AmigoCloud API key in the connection string, fix page size (github #137)
+
+GeoJSON driver:
+* fix segfaults on writing on NULL geometry with -lco WRITE_BBOX=YES (#6698)
+* support multilinestring from esriGeometryPolyline (#6773)
+
+GPKG driver:
+* don't show Spatialite vgpkg_ virtual tables (#6707)
+
+ILI1 driver:
+* make polygon reconstruction in Surface layers robust to curves not in natural order (#6728)
+
+MSSQL driver:
+* build optional mssql plugin with SQL Native Client support for MSSQL Bulk Copy
+
+NAS driver:
+* fix crash with enabled debugging
+
+SDE driver:
+* rename driver to OGR_SDE, and rename ICreateLayerFromRegInfo() as CreateLayerFromRegInfo() (#6714)
+
+Shape driver:
+* when rewriting the geometry of the last record in the .shp, do it at the file offset it previously used (#6787)
+
+SQLite driver:
+* Spatialite: do not report some BLOB columns as geometry columns of tables/views (when found before the geometry column(s)) (#6695, #6659)
+* fix update of features with multiple geometry columns (#6696)
+* Spatialite: avoid spatial views to cause layers 'layer_name(geometry_name)' to be publicly listed (#6740)
+* SQLite/GPKG: add explicit error message when trying to open a read-only WAL-enabled database, and make sure when closing a WAL-enabled database opened in read-only mode to reopen it in read-write mode so that the -wal and -shm files are removed (#6776)
+
+WFS driver:
+* fix potential nullptr dereference on dataset without layer (github #179)
+
+XLSX driver:
+* fix GDAL 2.1.2 regression regarding reading XLSX files whose sheet filenames are internally stored as 'absolute' (#6733)
+
+== Perl bindings ==
+* fix setting the geometry of a MultiLineString and MultiPolygon (#6786)
+
+== Python bindings ==
+* add outputType option to gdal.Rasterize() (#6710)
+* fix gdal.DEMProcessingOptions(zeroForFlat=True) (#6775)
+* swig/python/setup.py: fix build issues when CXX is defined in the environment (#6765)
+
 = GDAL/OGR 2.1.2 Release Notes = 
 
 The 2.1.2 release is a bug fix release.
diff --git a/VERSION b/VERSION
index eca07e4..ac2cdeb 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.2
+2.1.3
diff --git a/alg/gdalrasterize.cpp b/alg/gdalrasterize.cpp
index 2ffae51..38507ef 100644
--- a/alg/gdalrasterize.cpp
+++ b/alg/gdalrasterize.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalrasterize.cpp 33808 2016-03-29 21:15:28Z goatbar $
+ * $Id: gdalrasterize.cpp 36584 2016-11-30 17:46:24Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Vector rasterization.
@@ -566,6 +566,8 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
                                 void *pProgressArg )
 
 {
+    VALIDATE_POINTER1( hDS, "GDALRasterizeGeometries", CE_Failure);
+
     GDALDataType   eType;
     int            nYChunkSize, nScanlineBytes;
     unsigned char *pabyChunkBuf;
@@ -614,10 +616,26 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
     {
         bNeedToFreeTransformer = TRUE;
 
-        pTransformArg =
-            GDALCreateGenImgProjTransformer( NULL, NULL, hDS, NULL,
-                                             FALSE, 0.0, 0);
+        char** papszTransformerOptions = NULL;
+        double adfGeoTransform[6] = { 0 };
+        if( poDS->GetGeoTransform( adfGeoTransform ) != CE_None &&
+            poDS->GetGCPCount() == 0 &&
+            poDS->GetMetadata("RPC") == NULL )
+        {
+            papszTransformerOptions = CSLSetNameValue(
+                papszTransformerOptions, "DST_METHOD", "NO_GEOTRANSFORM");
+        }
+
+        pTransformArg = 
+            GDALCreateGenImgProjTransformer2( NULL, hDS,
+                                                papszTransformerOptions );
+        CSLDestroy( papszTransformerOptions );
+
         pfnTransformer = GDALGenImgProjTransform;
+        if( pTransformArg == NULL )
+        {
+            return CE_Failure;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -788,6 +806,8 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
                             void *pProgressArg )
 
 {
+    VALIDATE_POINTER1( hDS, "GDALRasterizeLayers", CE_Failure);
+
     GDALDataType   eType;
     unsigned char *pabyChunkBuf;
     GDALDataset *poDS = (GDALDataset *) hDS;
@@ -947,12 +967,31 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
             else
                 poSRS->exportToWkt( &pszProjection );
 
-            pTransformArg =
-                GDALCreateGenImgProjTransformer( NULL, pszProjection,
-                                                 hDS, NULL, FALSE, 0.0, 0 );
+            char** papszTransformerOptions = NULL;
+            if( pszProjection != NULL )
+                papszTransformerOptions = CSLSetNameValue(
+                        papszTransformerOptions, "SRC_SRS", pszProjection );
+            double adfGeoTransform[6] = { 0 };
+            if( poDS->GetGeoTransform( adfGeoTransform ) != CE_None &&
+                poDS->GetGCPCount() == 0 &&
+                poDS->GetMetadata("RPC") == NULL )
+            {
+                papszTransformerOptions = CSLSetNameValue(
+                    papszTransformerOptions, "DST_METHOD", "NO_GEOTRANSFORM");
+            }
+
+            pTransformArg = 
+                GDALCreateGenImgProjTransformer2( NULL, hDS,
+                                                  papszTransformerOptions );
             pfnTransformer = GDALGenImgProjTransform;
 
             CPLFree( pszProjection );
+            CSLDestroy( papszTransformerOptions );
+            if( pTransformArg == NULL )
+            {
+                CPLFree( pabyChunkBuf );
+                return CE_Failure;
+            }
         }
 
         OGRFeature *poFeat;
diff --git a/alg/gdaltransformer.cpp b/alg/gdaltransformer.cpp
index 8bd16b6..d534c3f 100644
--- a/alg/gdaltransformer.cpp
+++ b/alg/gdaltransformer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaltransformer.cpp 33715 2016-03-13 08:52:06Z goatbar $
+ * $Id: gdaltransformer.cpp 36584 2016-11-30 17:46:24Z rouault $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Implementation of one or more GDALTrasformerFunc types, including
@@ -38,7 +38,7 @@
 #include "cpl_list.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdaltransformer.cpp 33715 2016-03-13 08:52:06Z goatbar $");
+CPL_CVSID("$Id: gdaltransformer.cpp 36584 2016-11-30 17:46:24Z rouault $");
 CPL_C_START
 void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree );
 void *GDALDeserializeTPSTransformer( CPLXMLNode *psTree );
@@ -1448,7 +1448,9 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to compute a transformation between pixel/line\n"
                   "and georeferenced coordinates for %s.\n"
-                  "There is no affine transformation and no GCPs.",
+                  "There is no affine transformation and no GCPs.\n"
+                  "Specify transformation option DST_METHOD=NO_GEOTRANSFORM "
+                  "to bypass this check.",
                   GDALGetDescription( hDstDS ) );
 
         GDALDestroyGenImgProjTransformer( psInfo );
diff --git a/alg/gdalwarpkernel.cpp b/alg/gdalwarpkernel.cpp
index b5f2e4d..e9aa218 100644
--- a/alg/gdalwarpkernel.cpp
+++ b/alg/gdalwarpkernel.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarpkernel.cpp 33715 2016-03-13 08:52:06Z goatbar $
+ * $Id: gdalwarpkernel.cpp 36995 2016-12-22 11:36:36Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implementation of the GDALWarpKernel class.  Implements the actual
@@ -43,7 +43,7 @@
 #include <limits>
 #include <new>
 
-CPL_CVSID("$Id: gdalwarpkernel.cpp 33715 2016-03-13 08:52:06Z goatbar $");
+CPL_CVSID("$Id: gdalwarpkernel.cpp 36995 2016-12-22 11:36:36Z rouault $");
 
 //#define INSTANTIATE_FLOAT64_SSE2_IMPL
 
@@ -3947,16 +3947,27 @@ static CPL_INLINE int GWKCheckAndComputeSrcOffsets(const int* _pabSuccess,
         || _padfY[_iDstX] < _poWK->nSrcYOff )
         return FALSE;
 
+    // Check for potential overflow when casting from float to int, (if
+    // operating outside natural projection area, padfX/Y can be a very huge
+    // positive number before doing the actual conversion), as such cast is
+    // undefined behaviour that can trigger exception with some compilers
+    // (see #6753)
+    if( _padfX[_iDstX] + 1e-10 > _nSrcXSize + _poWK->nSrcXOff ||
+        _padfY[_iDstX] + 1e-10 > _nSrcYSize + _poWK->nSrcYOff )
+    {
+        return false;
+    }
+
     int iSrcX, iSrcY;
 
-    iSrcX = ((int) (_padfX[_iDstX] + 1e-10)) - _poWK->nSrcXOff;
-    iSrcY = ((int) (_padfY[_iDstX] + 1e-10)) - _poWK->nSrcYOff;
+    iSrcX = static_cast<int>(_padfX[_iDstX] + 1e-10) - _poWK->nSrcXOff;
+    iSrcY = static_cast<int>(_padfY[_iDstX] + 1e-10) - _poWK->nSrcYOff;
 
-    /* If operating outside natural projection area, padfX/Y can be */
-    /* a very huge positive number, that becomes -2147483648 in the */
-    /* int trucation. So it is necessary to test now for non negativeness. */
-    if( iSrcX < 0 || iSrcX >= _nSrcXSize || iSrcY < 0 || iSrcY >= _nSrcYSize )
-        return FALSE;
+    // Those checks should normally be OK given the previous ones.
+    CPLAssert( iSrcX >= 0 );
+    CPLAssert( iSrcY >= 0 );
+    CPLAssert( iSrcX < _nSrcXSize );
+    CPLAssert( iSrcY < _nSrcYSize );
 
     iSrcOffset = iSrcX + iSrcY * _nSrcXSize;
 
diff --git a/alg/gdalwarpkernel_opencl.c b/alg/gdalwarpkernel_opencl.c
index 4cb9284..c444578 100644
--- a/alg/gdalwarpkernel_opencl.c
+++ b/alg/gdalwarpkernel_opencl.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarpkernel_opencl.c 33715 2016-03-13 08:52:06Z goatbar $
+ * $Id: gdalwarpkernel_opencl.c 36105 2016-11-04 22:15:51Z rouault $
  *
  * Project:  OpenCL Image Reprojector
  * Purpose:  Implementation of the GDALWarpKernel reprojector in OpenCL.
@@ -41,7 +41,7 @@
 #include "cpl_string.h"
 #include "gdalwarpkernel_opencl.h"
 
-CPL_CVSID("$Id: gdalwarpkernel_opencl.c 33715 2016-03-13 08:52:06Z goatbar $");
+CPL_CVSID("$Id: gdalwarpkernel_opencl.c 36105 2016-11-04 22:15:51Z rouault $");
 
 #define handleErr(err) if((err) != CL_SUCCESS) { \
     CPLError(CE_Failure, CPLE_AppDefined, "Error at file %s line %d: %s", __FILE__, __LINE__, getCLErrorString(err)); \
@@ -317,7 +317,7 @@ cl_int set_supported_formats(struct oclWarper *warper,
 
     //Find what we *can* handle
     handleErr(err = clGetSupportedImageFormats(warper->context,
-                                               CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
+                                               CL_MEM_READ_ONLY,
                                                CL_MEM_OBJECT_IMAGE2D,
                                                256, fmtBuf, &numRet));
     for (i = 0; i < numRet; ++i) {
@@ -1249,8 +1249,7 @@ cl_kernel get_kernel(struct oclWarper *warper, char useVec,
             "-D PI=%015.15lff -D outType=%s -D dstMinVal=%015.15lff -D dstMaxVal=%015.15lff "
             "-D useDstNoDataReal=%d -D vecf=%s %s -D doCubicSpline=%d "
             "-D useUseBandSrcValid=%d -D iCoordMult=%d ",
-            /* FIXME: Is it really a ATI specific thing ? */
-            (warper->imageFormat == CL_FLOAT && (warper->eCLVendor == VENDOR_AMD || warper->eCLVendor == VENDOR_INTEL)) ? "-D USE_CLAMP_TO_DST_FLOAT=1 " : "",
+            (warper->imageFormat == CL_FLOAT) ? "-D USE_CLAMP_TO_DST_FLOAT=1 " : "",
             warper->srcWidth, warper->srcHeight, warper->dstWidth, warper->dstHeight,
             warper->useUnifiedSrcDensity, warper->useUnifiedSrcValid,
             warper->useDstDensity, warper->useDstValid, warper->imagWorkCL != NULL,
diff --git a/apps/gdal_rasterize_lib.cpp b/apps/gdal_rasterize_lib.cpp
index a2107d8..a0f66e2 100644
--- a/apps/gdal_rasterize_lib.cpp
+++ b/apps/gdal_rasterize_lib.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rasterize_lib.cpp 34044 2016-04-21 08:23:14Z rouault $
+ * $Id: gdal_rasterize_lib.cpp 36584 2016-11-30 17:46:24Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Rasterize OGR shapes into a GDAL raster.
@@ -38,7 +38,7 @@
 #include "gdal_utils_priv.h"
 #include <vector>
 
-CPL_CVSID("$Id: gdal_rasterize_lib.cpp 34044 2016-04-21 08:23:14Z rouault $");
+CPL_CVSID("$Id: gdal_rasterize_lib.cpp 36584 2016-11-30 17:46:24Z rouault $");
 
 /************************************************************************/
 /*                            ArgIsNumeric()                            */
@@ -585,7 +585,7 @@ GDALDatasetH GDALRasterize( const char *pszDest, GDALDatasetH hDstDS,
         bCreateOutput = TRUE;
 
     GDALDriverH hDriver = NULL;
-    if (psOptions->bCreateOutput)
+    if (bCreateOutput)
     {
 /* -------------------------------------------------------------------- */
 /*      Find the output driver.                                         */
@@ -665,7 +665,7 @@ GDALDatasetH GDALRasterize( const char *pszDest, GDALDatasetH hDstDS,
 /* -------------------------------------------------------------------- */
     int nLayerCount = (psOptions->pszSQL == NULL && psOptions->papszLayers == NULL) ? 1 : CSLCount(psOptions->papszLayers);
 
-    if (psOptions->bCreateOutput && hDstDS == NULL)
+    if (bCreateOutput && hDstDS == NULL)
     {
         std::vector<OGRLayerH> ahLayers;
 
@@ -787,7 +787,6 @@ GDALRasterizeOptions *GDALRasterizeOptionsNew(char** papszArgv,
     psOptions->papszRasterizeOptions = NULL;
     psOptions->dfXRes = 0;
     psOptions->dfYRes = 0;
-    psOptions->bCreateOutput = FALSE;
     psOptions->eOutputType = GDT_Float64;
     psOptions->bNoDataSet = FALSE;
     psOptions->dfNoData = 0;
diff --git a/apps/gdalinfo_lib.cpp b/apps/gdalinfo_lib.cpp
index 19c5866..dc84056 100644
--- a/apps/gdalinfo_lib.cpp
+++ b/apps/gdalinfo_lib.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalinfo_lib.cpp 33615 2016-03-02 20:19:22Z goatbar $
+ * $Id: gdalinfo_lib.cpp 36077 2016-11-02 12:41:41Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Command line application to list info about a file.
@@ -45,7 +45,7 @@
 
 using std::vector;
 
-CPL_CVSID("$Id: gdalinfo_lib.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+CPL_CVSID("$Id: gdalinfo_lib.cpp 36077 2016-11-02 12:41:41Z rouault $");
 
 /*! output format */
 typedef enum {
@@ -563,11 +563,11 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                               0.0, 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
         GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "lowerLeft",
                               0.0, GDALGetRasterYSize(hDataset), bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
-        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "upperRight",
-                              GDALGetRasterXSize(hDataset), 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
         GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "lowerRight",
                               GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset),
                               bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "upperRight",
+                              GDALGetRasterXSize(hDataset), 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
         GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "center",
                               GDALGetRasterXSize(hDataset)/2.0, GDALGetRasterYSize(hDataset)/2.0,
                               bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
diff --git a/configure b/configure
index 1ae229b..0ecb455 100755
--- a/configure
+++ b/configure
@@ -898,6 +898,7 @@ infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -1090,6 +1091,7 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE}'
@@ -1342,6 +1344,15 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1479,7 +1490,7 @@ fi
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir
+		libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1632,6 +1643,7 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -18130,6 +18142,17 @@ _ACEOF
 fi
 done
 
+for ac_func in statvfs64
+do :
+  ac_fn_c_check_func "$LINENO" "statvfs64" "ac_cv_func_statvfs64"
+if test "x$ac_cv_func_statvfs64" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STATVFS64 1
+_ACEOF
+
+fi
+done
+
 
 
 ac_ext=cpp
diff --git a/configure.in b/configure.in
index cd705fe..556d2ab 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: configure.in 34263 2016-05-23 15:45:52Z rouault $
+dnl $Id: configure.in 36874 2016-12-15 01:53:28Z rouault $
 dnl
 dnl Project:  GDAL
 dnl Purpose:  Configure source file.
@@ -209,6 +209,7 @@ AC_CHECK_FUNCS(posix_spawnp)
 AC_CHECK_FUNCS(vfork)
 AC_CHECK_FUNCS(mmap)
 AC_CHECK_FUNCS(statvfs)
+AC_CHECK_FUNCS(statvfs64)
 
 dnl Make sure at least these are checked under C++.  Prototypes missing on
 dnl some platforms.
diff --git a/frmts/adrg/adrgdataset.cpp b/frmts/adrg/adrgdataset.cpp
index 17cff86..79e989b 100644
--- a/frmts/adrg/adrgdataset.cpp
+++ b/frmts/adrg/adrgdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: adrgdataset.cpp 33901 2016-04-06 16:31:31Z goatbar $
+ * $Id: adrgdataset.cpp 37158 2017-01-16 18:05:41Z rouault $
  *
  * Purpose:  ADRG reader
  * Author:   Even Rouault, even.rouault at mines-paris.org
@@ -32,7 +32,7 @@
 #include "iso8211.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: adrgdataset.cpp 33901 2016-04-06 16:31:31Z goatbar $");
+CPL_CVSID("$Id: adrgdataset.cpp 37158 2017-01-16 18:05:41Z rouault $");
 
 #define N_ELEMENTS(x)  (sizeof(x)/sizeof(x[0]))
 
@@ -42,6 +42,7 @@ class ADRGDataset : public GDALPamDataset
 
     CPLString    osGENFileName;
     CPLString    osIMGFileName;
+    CPLString    osSRS;
 
     VSILFILE*        fdIMG;
     int*         TILEINDEX;
@@ -717,7 +718,7 @@ char **ADRGDataset::GetMetadata( const char *pszDomain )
 
 const char* ADRGDataset::GetProjectionRef()
 {
-    return( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]]" );
+    return osSRS;
 }
 
 /************************************************************************/
@@ -1098,14 +1099,6 @@ ADRGDataset* ADRGDataset::OpenDataset(
         return NULL;
     }
 
-    if (ZNA == 9 || ZNA == 18)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Polar cases are not handled by ADRG driver");
-        VSIFCloseL(fdIMG);
-        delete[] TILEINDEX;
-        return NULL;
-    }
-
     /* Skip ISO8211 header of IMG file */
     int offsetInIMG = 0;
     char c;
@@ -1187,19 +1180,62 @@ ADRGDataset* ADRGDataset::OpenDataset(
     poDS->offsetInIMG = offsetInIMG;
     poDS->poOverviewDS = NULL;
 
-    poDS->adfGeoTransform[0] = LSO;
-    poDS->adfGeoTransform[1] = 360. / ARV;
-    poDS->adfGeoTransform[2] = 0.0;
-    poDS->adfGeoTransform[3] = PSO;
-    poDS->adfGeoTransform[4] = 0.0;
-    poDS->adfGeoTransform[5] = - 360. / BRV;
+    if( ZNA == 9)
+    {
+        // North Polar Case
+        poDS->adfGeoTransform[0] = 111319.4907933 * (90.0 - PSO) * sin(LSO * M_PI / 180.0);
+        poDS->adfGeoTransform[1] = 40075016.68558 / ARV;
+        poDS->adfGeoTransform[2] = 0.0;
+        poDS->adfGeoTransform[3] = -111319.4907933 * (90.0 - PSO) * cos(LSO * M_PI / 180.0);
+        poDS->adfGeoTransform[4] = 0.0;
+        poDS->adfGeoTransform[5] = -40075016.68558 / ARV;
+        poDS->osSRS =
+                "PROJCS[\"ARC_System_Zone_09\",GEOGCS[\"GCS_Sphere\","
+                "DATUM[\"D_Sphere\",SPHEROID[\"Sphere\",6378137.0,0.0]],"
+                "PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],"
+                "PROJECTION[\"Azimuthal_Equidistant\"],"
+                "PARAMETER[\"latitude_of_center\",90],"
+                "PARAMETER[\"longitude_of_center\",0],"
+                "PARAMETER[\"false_easting\",0],"
+                "PARAMETER[\"false_northing\",0]]";
+    }
+    else if (ZNA == 18)
+    {
+        // South Polar Case
+        poDS->adfGeoTransform[0] = 111319.4907933 * (90.0 + PSO) * sin(LSO * M_PI / 180.0);
+        poDS->adfGeoTransform[1] = 40075016.68558 / ARV;
+        poDS->adfGeoTransform[2] = 0.0;
+        poDS->adfGeoTransform[3] = 111319.4907933 * (90.0 + PSO) * cos(LSO * M_PI / 180.0);
+        poDS->adfGeoTransform[4] = 0.0;
+        poDS->adfGeoTransform[5] = -40075016.68558 / ARV;
+        poDS->osSRS = "PROJCS[\"ARC_System_Zone_18\",GEOGCS[\"GCS_Sphere\","
+                "DATUM[\"D_Sphere\",SPHEROID[\"Sphere\",6378137.0,0.0]],"
+                "PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],"
+                "PROJECTION[\"Azimuthal_Equidistant\"],"
+                "PARAMETER[\"latitude_of_center\",-90],"
+                "PARAMETER[\"longitude_of_center\",0],"
+                "PARAMETER[\"false_easting\",0],"
+                "PARAMETER[\"false_northing\",0]]";
+    }
+    else
+    {
+        poDS->adfGeoTransform[0] = LSO;
+        poDS->adfGeoTransform[1] = 360. / ARV;
+        poDS->adfGeoTransform[2] = 0.0;
+        poDS->adfGeoTransform[3] = PSO;
+        poDS->adfGeoTransform[4] = 0.0;
+        poDS->adfGeoTransform[5] = - 360. / BRV;
+        poDS->osSRS = SRS_WKT_WGS84;
+    }
 
     // if (isGIN)
     {
         char szValue[32];
         snprintf( szValue, sizeof(szValue), "%d", SCA);
         poDS->SetMetadataItem( "ADRG_SCA", szValue );
-    }
+        snprintf( szValue, sizeof(szValue), "%d", ZNA);
+        poDS->SetMetadataItem( "ADRG_ZNA", szValue );
+     }
 
     poDS->SetMetadataItem( "ADRG_NAM", osNAM.c_str() );
 
diff --git a/frmts/dods/dodsdataset2.cpp b/frmts/dods/dodsdataset2.cpp
index f046f70..7147a41 100644
--- a/frmts/dods/dodsdataset2.cpp
+++ b/frmts/dods/dodsdataset2.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dodsdataset2.cpp 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: dodsdataset2.cpp 36175 2016-11-09 09:31:39Z rouault $
  *
  * Project:  OPeNDAP Raster Driver
  * Purpose:  Implements DODSDataset and DODSRasterBand classes.
@@ -72,7 +72,7 @@
 
 using namespace libdap;
 
-CPL_CVSID("$Id: dodsdataset2.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: dodsdataset2.cpp 36175 2016-11-09 09:31:39Z rouault $");
 
 /** Attribute names used to encode geo-referencing information. Note that
     these are not C++ objects to avoid problems with static global
@@ -496,6 +496,8 @@ char **DODSDataset::CollectBandsFromDDSVar( string oVarName,
 /* -------------------------------------------------------------------- */
     BaseType *poVar = get_variable( GetDDS(), oVarName );
 
+    if( poVar == NULL )
+        return papszResultList;
     if( poVar->type() == dods_array_c )
     {
         poGrid = NULL;
@@ -1024,7 +1026,11 @@ DODSDataset::Open(GDALOpenInfo *poOpenInfo)
 /*      Did we get any target variables?                                */
 /* -------------------------------------------------------------------- */
         if( CSLCount(papszVarConstraintList) == 0 )
-            throw Error( "No apparent raster grids or arrays found in DDS.");
+        {
+            CPLDebug( "DODS", "No apparent raster grids or arrays found in DDS.");
+            delete poDS;
+            return NULL;
+        }
 
 /* -------------------------------------------------------------------- */
 /*      For now we support only a single band.                          */
diff --git a/frmts/grass/pkg/Makefile.in b/frmts/grass/pkg/Makefile.in
index 9bac96a..568d554 100644
--- a/frmts/grass/pkg/Makefile.in
+++ b/frmts/grass/pkg/Makefile.in
@@ -14,8 +14,6 @@ LD_SHARED	=	@LD_SHARED@
 
 LIBS	=	@LIBS@
 
-GRASSTABLES_DIR = @prefix@/share/gdal/grass
-
 AUTOLOAD_DIR	=	@AUTOLOAD_DIR@
 
 GLIBNAME =	gdal_GRASS.so
@@ -27,17 +25,6 @@ install:	default
 	install -d $(AUTOLOAD_DIR)
 	cp $(GLIBNAME) $(AUTOLOAD_DIR)
 	cp $(OLIBNAME) $(AUTOLOAD_DIR)
-	test -d ${GRASSTABLES_DIR} || mkdir ${GRASSTABLES_DIR}
-	test -d ${GRASSTABLES_DIR}/etc || mkdir ${GRASSTABLES_DIR}/etc
-	test ! -e @GRASS_GISBASE@/etc/ellipse.table || cp @GRASS_GISBASE@/etc/ellipse.table ${GRASSTABLES_DIR}/etc
-	test ! -e @GRASS_GISBASE@/etc/datum.table || cp @GRASS_GISBASE@/etc/datum.table ${GRASSTABLES_DIR}/etc
-	test ! -e @GRASS_GISBASE@/etc/datumtransform.table || cp @GRASS_GISBASE@/etc/datumtransform.table ${GRASSTABLES_DIR}/etc
-	test ! -e @GRASS_GISBASE@/etc/proj/ellipse.table || cp @GRASS_GISBASE@/etc/proj/ellipse.table ${GRASSTABLES_DIR}/etc
-	test ! -e @GRASS_GISBASE@/etc/proj/datum.table || cp @GRASS_GISBASE@/etc/proj/datum.table ${GRASSTABLES_DIR}/etc
-	test ! -e @GRASS_GISBASE@/etc/proj/datumtransform.table || cp @GRASS_GISBASE@/etc/proj/datumtransform.table ${GRASSTABLES_DIR}/etc
-	test -d ${GRASSTABLES_DIR}/driver || mkdir ${GRASSTABLES_DIR}/driver
-	test -d ${GRASSTABLES_DIR}/driver/db || mkdir ${GRASSTABLES_DIR}/driver/db
-	cp -r @GRASS_GISBASE@/driver/db/* ${GRASSTABLES_DIR}/driver/db/
 
 clean:
 	rm -f $(OLIBNAME) $(GLIBNAME) *.o
diff --git a/frmts/grass/pkg/configure b/frmts/grass/pkg/configure
index ae5e319..39649f1 100755
--- a/frmts/grass/pkg/configure
+++ b/frmts/grass/pkg/configure
@@ -626,6 +626,7 @@ infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -703,6 +704,7 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE}'
@@ -955,6 +957,15 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1092,7 +1103,7 @@ fi
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir
+		libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1245,6 +1256,7 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -3279,7 +3291,50 @@ fi
 if test "$with_grass" != "yes" ; then
 
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for G_is_initialized in -lgrass_gis" >&5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for G_read_compressed in -lgrass_gis" >&5
+$as_echo_n "checking for G_read_compressed in -lgrass_gis... " >&6; }
+if ${ac_cv_lib_grass_gis_G_read_compressed+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgrass_gis -L$with_grass/lib -lgrass_datetime $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char G_read_compressed ();
+int
+main ()
+{
+return G_read_compressed ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_grass_gis_G_read_compressed=yes
+else
+  ac_cv_lib_grass_gis_G_read_compressed=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_grass_gis_G_read_compressed" >&5
+$as_echo "$ac_cv_lib_grass_gis_G_read_compressed" >&6; }
+if test "x$ac_cv_lib_grass_gis_G_read_compressed" = xyes; then :
+  GRASS_SETTING=grass72+
+else
+  GRASS_SETTING=no
+fi
+
+  if test "$GRASS_SETTING" = "no" ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for G_is_initialized in -lgrass_gis" >&5
 $as_echo_n "checking for G_is_initialized in -lgrass_gis... " >&6; }
 if ${ac_cv_lib_grass_gis_G_is_initialized+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -3321,8 +3376,8 @@ else
   GRASS_SETTING=no
 fi
 
-  if test "$GRASS_SETTING" = "no" ; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for G_asprintf in -lgrass_gis" >&5
+    if test "$GRASS_SETTING" = "no" ; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for G_asprintf in -lgrass_gis" >&5
 $as_echo_n "checking for G_asprintf in -lgrass_gis... " >&6; }
 if ${ac_cv_lib_grass_gis_G_asprintf+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -3364,10 +3419,15 @@ else
   GRASS_SETTING=no
 fi
 
+    fi
   fi
 
   if test "$GRASS_SETTING" != "no" ; then
-    if test "$GRASS_SETTING" = "grass70+" ; then
+    if test "$GRASS_SETTING" = "grass72+" ; then
+      G_RASTLIBS="-lgrass_raster -lgrass_imagery"
+      G_VECTLIBS="-lgrass_vector -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
+      LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_gmath -lgrass_gis -lgrass_datetime -lgrass_btree2 -lgrass_ccmath $LIBS"
+    elif test "$GRASS_SETTING" = "grass70+" ; then
       G_RASTLIBS="-lgrass_raster -lgrass_imagery"
       G_VECTLIBS="-lgrass_vector -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
       LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_gmath -lgrass_gis -lgrass_datetime $LIBS"
diff --git a/frmts/grass/pkg/configure.in b/frmts/grass/pkg/configure.in
index a0cfa9c..ff96173 100644
--- a/frmts/grass/pkg/configure.in
+++ b/frmts/grass/pkg/configure.in
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: configure.in 33717 2016-03-14 06:29:14Z goatbar $
+dnl $Id: configure.in 37161 2017-01-17 07:34:30Z rouault $
 dnl
 dnl Project:  GDAL GRASS Plugin
 dnl Purpose:  Configure source file.
@@ -123,13 +123,20 @@ fi
 
 if test "$with_grass" != "yes" ; then
 
-  AC_CHECK_LIB(grass_gis,G_is_initialized,GRASS_SETTING=grass70+,GRASS_SETTING=no,-L$with_grass/lib -lgrass_datetime)
+  AC_CHECK_LIB(grass_gis,G_read_compressed,GRASS_SETTING=grass72+,GRASS_SETTING=no,-L$with_grass/lib -lgrass_datetime)
   if test "$GRASS_SETTING" = "no" ; then
-    AC_CHECK_LIB(grass_gis,G_asprintf,GRASS_SETTING=grass57+,GRASS_SETTING=no,-L$with_grass/lib -lgrass_datetime)
+    AC_CHECK_LIB(grass_gis,G_is_initialized,GRASS_SETTING=grass70+,GRASS_SETTING=no,-L$with_grass/lib -lgrass_datetime)
+    if test "$GRASS_SETTING" = "no" ; then
+      AC_CHECK_LIB(grass_gis,G_asprintf,GRASS_SETTING=grass57+,GRASS_SETTING=no,-L$with_grass/lib -lgrass_datetime)
+    fi
   fi
 
   if test "$GRASS_SETTING" != "no" ; then
-    if test "$GRASS_SETTING" = "grass70+" ; then
+    if test "$GRASS_SETTING" = "grass72+" ; then
+      G_RASTLIBS="-lgrass_raster -lgrass_imagery"
+      G_VECTLIBS="-lgrass_vector -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
+      LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_gmath -lgrass_gis -lgrass_datetime -lgrass_btree2 -lgrass_ccmath $LIBS"
+    elif test "$GRASS_SETTING" = "grass70+" ; then
       G_RASTLIBS="-lgrass_raster -lgrass_imagery"
       G_VECTLIBS="-lgrass_vector -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
       LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_gmath -lgrass_gis -lgrass_datetime $LIBS"
diff --git a/frmts/gtiff/geotiff.cpp b/frmts/gtiff/geotiff.cpp
index b7616d8..d9e6044 100644
--- a/frmts/gtiff/geotiff.cpp
+++ b/frmts/gtiff/geotiff.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geotiff.cpp 35365 2016-09-08 07:53:35Z rouault $
+ * $Id: geotiff.cpp 37071 2017-01-07 20:49:39Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  GDAL GeoTIFF support.
@@ -65,7 +65,7 @@
 #include "tifvsi.h"
 #include "xtiffio.h"
 
-CPL_CVSID("$Id: geotiff.cpp 35365 2016-09-08 07:53:35Z rouault $");
+CPL_CVSID("$Id: geotiff.cpp 37071 2017-01-07 20:49:39Z rouault $");
 
 #if SIZEOF_VOIDP == 4
 static int bGlobalStripIntegerOverflow = FALSE;
@@ -12343,6 +12343,7 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Streaming related code                                          */
 /* -------------------------------------------------------------------- */
+    const CPLString osOriFilename(pszFilename);
     int bStreaming = ( strcmp(pszFilename, "/vsistdout/") == 0 ||
                        CSLFetchBoolean(papszParmList, "STREAMABLE_OUTPUT", FALSE) );
 #ifdef S_ISFIFO
@@ -12407,6 +12408,8 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
     if( nCompression == COMPRESSION_NONE &&
         dfUncompressedImageSize >= 1e9 &&
         !CSLFetchBoolean(papszParmList, "SPARSE_OK", FALSE) &&
+        osOriFilename != "/vsistdout/" &&
+        osOriFilename != "/vsistdout_redirect/" &&
         CPLTestBool(CPLGetConfigOption("CHECK_DISK_FREE_SPACE", "TRUE")) )
     {
         GIntBig nFreeDiskSpace = VSIGetDiskFreeSpace(CPLGetDirname(pszFilename));
@@ -12804,12 +12807,10 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
     }
     else
     {
-        uint32 nRowsPerStrip;
-
-        if( nBlockYSize == 0 )
-            nRowsPerStrip = MIN(nYSize, (int)TIFFDefaultStripSize(hTIFF,0));
-        else
-            nRowsPerStrip = nBlockYSize;
+        const uint32 nRowsPerStrip = MIN(nYSize,
+            (nBlockYSize == 0
+            ? static_cast<int>(TIFFDefaultStripSize(hTIFF,0))
+            : nBlockYSize) );
 
         TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nRowsPerStrip );
     }
diff --git a/frmts/hdf4/hdf4dataset.cpp b/frmts/hdf4/hdf4dataset.cpp
index de45167..0b390a6 100644
--- a/frmts/hdf4/hdf4dataset.cpp
+++ b/frmts/hdf4/hdf4dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf4dataset.cpp 35036 2016-08-10 12:11:37Z rouault $
+ * $Id: hdf4dataset.cpp 35971 2016-10-27 11:27:35Z jef $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  HDF4 Datasets. Open HDF4 file, fetch metadata and list of
@@ -40,9 +40,10 @@
 
 #include "HdfEosDef.h"
 
+#include "hdf4compat.h"
 #include "hdf4dataset.h"
 
-CPL_CVSID("$Id: hdf4dataset.cpp 35036 2016-08-10 12:11:37Z rouault $");
+CPL_CVSID("$Id: hdf4dataset.cpp 35971 2016-10-27 11:27:35Z jef $");
 
 extern const char * const pszGDALSignature;
 
diff --git a/frmts/idrisi/IdrisiDataset.cpp b/frmts/idrisi/IdrisiDataset.cpp
index 5be3936..998feaa 100644
--- a/frmts/idrisi/IdrisiDataset.cpp
+++ b/frmts/idrisi/IdrisiDataset.cpp
@@ -1,5 +1,5 @@
 /*****************************************************************************
-* $Id: IdrisiDataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
+* $Id: IdrisiDataset.cpp 36496 2016-11-25 13:09:32Z rouault $
 *
 * Project:  Idrisi Raster Image File Driver
 * Purpose:  Read/write Idrisi Raster Image Format RST
@@ -43,7 +43,7 @@
 #include "ogr_spatialref.h"
 #include "idrisi.h"
 
-CPL_CVSID( "$Id: IdrisiDataset.cpp 33720 2016-03-15 00:39:53Z goatbar $" );
+CPL_CVSID( "$Id: IdrisiDataset.cpp 36496 2016-11-25 13:09:32Z rouault $" );
 
 #ifdef WIN32
 #  define PATHDELIM       '\\'
@@ -1177,11 +1177,13 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
     // --------------------------------------------------------------------
 
     double adfGeoTransform[6];
+    if(  poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None )
+    {
+        poDS->SetGeoTransform(adfGeoTransform);
+    }
 
     if (!EQUAL(poSrcDS->GetProjectionRef(),""))
     {
-        poSrcDS->GetGeoTransform(adfGeoTransform);
-        poDS->SetGeoTransform(adfGeoTransform);
         poDS->SetProjection( poSrcDS->GetProjectionRef() );
     }
 
diff --git a/frmts/netcdf/netcdfdataset.cpp b/frmts/netcdf/netcdfdataset.cpp
index ab4fdc2..ae2f7b5 100644
--- a/frmts/netcdf/netcdfdataset.cpp
+++ b/frmts/netcdf/netcdfdataset.cpp
@@ -1,6 +1,6 @@
 
 /******************************************************************************
- * $Id: netcdfdataset.cpp 35360 2016-09-08 00:35:56Z rouault $
+ * $Id: netcdfdataset.cpp 37032 2016-12-29 13:25:51Z rouault $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library.
@@ -40,7 +40,7 @@
 #include <map> //for NCDFWriteProjAttribs()
 #include <limits>
 
-CPL_CVSID("$Id: netcdfdataset.cpp 35360 2016-09-08 00:35:56Z rouault $");
+CPL_CVSID("$Id: netcdfdataset.cpp 37032 2016-12-29 13:25:51Z rouault $");
 
 /* Internal function declarations */
 
@@ -8766,6 +8766,32 @@ static bool NCDFIsVarProjectionY( int nCdfId, int nVarId, const char * pszVarNam
         else
             bVal = FALSE;
     }
+    else if ( bVal )
+    {
+        // Check that the units is not 'm'. See #6759
+        char *pszTemp = NULL;
+        if( NCDFGetAttr( nCdfId, nVarId, "units", &pszTemp ) == CE_None &&
+            pszTemp != NULL )
+        {
+            if( EQUAL( pszTemp, "m") )
+                bVal = false;
+            CPLFree( pszTemp );
+        }
+    }
+
+    else if ( bVal )
+    {
+        // Check that the units is not 'm'. See #6759
+        char *pszTemp = NULL;
+        if( NCDFGetAttr( nCdfId, nVarId, "units", &pszTemp ) == CE_None &&
+            pszTemp != NULL )
+        {
+            if( EQUAL( pszTemp, "m") )
+                bVal = false;
+            CPLFree( pszTemp );
+        }
+    }
+
     return CPL_TO_BOOL(bVal);
 }
 
diff --git a/frmts/openjpeg/openjpegdataset.cpp b/frmts/openjpeg/openjpegdataset.cpp
index 4269007..2d6aaa9 100644
--- a/frmts/openjpeg/openjpegdataset.cpp
+++ b/frmts/openjpeg/openjpegdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: openjpegdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: openjpegdataset.cpp 36187 2016-11-09 15:20:50Z rouault $
  *
  * Project:  JPEG2000 driver based on OpenJPEG library
  * Purpose:  JPEG2000 driver based on OpenJPEG library
@@ -46,7 +46,7 @@
 #include "gdaljp2metadata.h"
 #include "vrt/vrtdataset.h"
 
-CPL_CVSID("$Id: openjpegdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: openjpegdataset.cpp 36187 2016-11-09 15:20:50Z rouault $");
 
 /************************************************************************/
 /*                  JP2OpenJPEGDataset_ErrorCallback()                  */
@@ -1690,8 +1690,18 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else if (poDS->bUseSetDecodeArea)
     {
-        if (nTileW > 1024) nTileW = 1024;
-        if (nTileH > 1024) nTileH = 1024;
+        // Arbitrary threshold... ~4 million at least needed for the GRIB2
+        // images mentionned below.
+        if( nTileH == 1 && nTileW < 20 * 1024 * 1024 )
+        {
+            // Some GRIB2 JPEG2000 compressed images are a 2D image organized
+            // as a single line image...
+        }
+        else
+        {
+            if (nTileW > 1024) nTileW = 1024;
+            if (nTileH > 1024) nTileH = 1024;
+        }
     }
 
     GDALColorTable* poCT = NULL;
diff --git a/frmts/pcidsk/pcidskdataset2.cpp b/frmts/pcidsk/pcidskdataset2.cpp
index ecb1054..fe6f88d 100644
--- a/frmts/pcidsk/pcidskdataset2.cpp
+++ b/frmts/pcidsk/pcidskdataset2.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcidskdataset2.cpp 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: pcidskdataset2.cpp 37163 2017-01-17 08:11:27Z rouault $
  *
  * Project:  PCIDSK Database File
  * Purpose:  Read/write PCIDSK Database File used by the PCI software, using
@@ -32,7 +32,7 @@
 #include "gdal_frmts.h"
 #include "pcidskdataset2.h"
 
-CPL_CVSID("$Id: pcidskdataset2.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: pcidskdataset2.cpp 37163 2017-01-17 08:11:27Z rouault $");
 
 const PCIDSK::PCIDSKInterfaces *PCIDSK2GetInterfaces(void);
 
@@ -155,6 +155,13 @@ PCIDSK2Band::~PCIDSK2Band()
 void PCIDSK2Band::SetDescription( const char *pszDescription )
 
 {
+    if( GetAccess() == GA_ReadOnly )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Unable to set description on read-only file." );
+        return;
+    }
+
     try
     {
         poChannel->SetDescription( pszDescription );
@@ -397,6 +404,13 @@ CPLErr PCIDSK2Band::SetColorTable( GDALColorTable *poCT )
     if( poFile == NULL )
         return CE_Failure;
 
+    if( GetAccess() == GA_ReadOnly )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Unable to set color table on read-only file." );
+        return CE_Failure;
+    }
+
     try
     {
 /* -------------------------------------------------------------------- */
@@ -615,6 +629,13 @@ CPLErr PCIDSK2Band::SetMetadata( char **papszMD,
     CSLDestroy( papszLastMDListValue );
     papszLastMDListValue = NULL;
 
+    if( GetAccess() == GA_ReadOnly )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Unable to set metadata on read-only file." );
+        return CE_Failure;
+    }
+
     try
     {
         for( int iItem = 0; papszMD && papszMD[iItem]; iItem++ )
@@ -661,6 +682,13 @@ CPLErr PCIDSK2Band::SetMetadataItem( const char *pszName,
     CSLDestroy( papszLastMDListValue );
     papszLastMDListValue = NULL;
 
+    if( GetAccess() == GA_ReadOnly )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Unable to set metadata on read-only file." );
+        return CE_Failure;
+    }
+
     try
     {
         if( !pszValue )
@@ -1038,6 +1066,13 @@ CPLErr PCIDSK2Dataset::SetMetadata( char **papszMD,
     CSLDestroy( papszLastMDListValue );
     papszLastMDListValue = NULL;
 
+    if( GetAccess() == GA_ReadOnly )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Unable to set metadata on read-only file." );
+        return CE_Failure;
+    }
+
     try
     {
         for( int iItem = 0; papszMD && papszMD[iItem]; iItem++ )
@@ -1083,6 +1118,13 @@ CPLErr PCIDSK2Dataset::SetMetadataItem( const char *pszName,
     CSLDestroy( papszLastMDListValue );
     papszLastMDListValue = NULL;
 
+    if( GetAccess() == GA_ReadOnly )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Unable to set metadata on read-only file." );
+        return CE_Failure;
+    }
+
     try
     {
         poFile->SetMetadataValue( pszName, pszValue );
@@ -1210,6 +1252,13 @@ CPLErr PCIDSK2Dataset::SetGeoTransform( double * padfTransform )
     if( poGeoref == NULL )
         return GDALPamDataset::SetGeoTransform( padfTransform );
 
+    if( GetAccess() == GA_ReadOnly )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Unable to set GeoTransform on read-only file." );
+        return CE_Failure;
+    }
+
     try
     {
         poGeoref->WriteSimple( poGeoref->GetGeosys(),
@@ -1325,6 +1374,16 @@ CPLErr PCIDSK2Dataset::SetProjection( const char *pszWKT )
         return GDALPamDataset::SetProjection( pszWKT );
     }
 
+    if( GetAccess() == GA_ReadOnly )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Unable to set projection on read-only file." );
+        CPLFree( pszGeosys );
+        CPLFree( pszUnits );
+        CPLFree( padfPrjParams );
+        return CE_Failure;
+    }
+
     try
     {
         double adfGT[6];
diff --git a/frmts/pcidsk/sdk/segment/metadatasegment_p.cpp b/frmts/pcidsk/sdk/segment/metadatasegment_p.cpp
index cce31fa..ef9e7f1 100644
--- a/frmts/pcidsk/sdk/segment/metadatasegment_p.cpp
+++ b/frmts/pcidsk/sdk/segment/metadatasegment_p.cpp
@@ -30,6 +30,7 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "pcidsk_exception.h"
 #include "pcidsk_file.h"
 #include "segment/metadatasegment.h"
 #include <cassert>
@@ -58,7 +59,22 @@ MetadataSegment::MetadataSegment( PCIDSKFile *fileIn, int segmentIn,
 MetadataSegment::~MetadataSegment()
 
 {
-    Synchronize();
+    try
+    {
+        Synchronize();
+    }
+    catch( const PCIDSKException& ex )
+    {
+        fprintf( stderr, /*ok*/
+                 "Exception in MetadataSegment destructor: %s\n",
+                 ex.what() );
+    }
+    catch( ... )
+    {
+        fprintf( stderr, /*ok*/
+                 "PCIDSK SDK Failure in MetadataSegment destructor, "
+                 "unexpected exception.\n" );
+    }
 }
 
 /************************************************************************/
diff --git a/frmts/rmf/rmfdataset.cpp b/frmts/rmf/rmfdataset.cpp
index bc99bf7..c86706e 100644
--- a/frmts/rmf/rmfdataset.cpp
+++ b/frmts/rmf/rmfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rmfdataset.cpp 35853 2016-10-21 09:29:55Z rouault $
+ * $Id: rmfdataset.cpp 36638 2016-12-02 19:08:00Z rouault $
  *
  * Project:  Raster Matrix Format
  * Purpose:  Read/write raster files used in GIS "Integratsia"
@@ -34,7 +34,7 @@
 
 #include "rmfdataset.h"
 
-CPL_CVSID("$Id: rmfdataset.cpp 35853 2016-10-21 09:29:55Z rouault $");
+CPL_CVSID("$Id: rmfdataset.cpp 36638 2016-12-02 19:08:00Z rouault $");
 
 static const int RMF_DEFAULT_BLOCKXSIZE = 256;
 static const int RMF_DEFAULT_BLOCKYSIZE = 256;
@@ -1254,23 +1254,7 @@ do {                                                                    \
                 abyHeader + 248, sizeof(poDS->sHeader.abyInvisibleColors) );
         RMF_READ_DOUBLE( abyHeader, poDS->sHeader.adfElevMinMax[0], 280 );
         RMF_READ_DOUBLE( abyHeader, poDS->sHeader.adfElevMinMax[1], 288 );
-
-        if (poDS->sHeader.nBitDepth == 8)
-        {
-            poDS->sHeader.dfNoData = *reinterpret_cast<char *>(abyHeader + 296);
-        }
-        else if (poDS->sHeader.nBitDepth == 16)
-        {
-            RMF_READ_SHORT(abyHeader, poDS->sHeader.dfNoData, 296);
-        }
-        else if (poDS->sHeader.nBitDepth == 32)
-        {
-            RMF_READ_LONG(abyHeader, poDS->sHeader.dfNoData, 296);
-        }
-        else if (poDS->sHeader.nBitDepth == 64)
-        {
-            RMF_READ_DOUBLE(abyHeader, poDS->sHeader.dfNoData, 296);
-        }
+        RMF_READ_DOUBLE(abyHeader, poDS->sHeader.dfNoData, 296);
 
         RMF_READ_ULONG( abyHeader, poDS->sHeader.iElevationUnit, 304 );
         poDS->sHeader.iElevationType = *(abyHeader + 308);
diff --git a/frmts/sentinel2/frmt_sentinel2.html b/frmts/sentinel2/frmt_sentinel2.html
index aaa359a..d2b6b4c 100644
--- a/frmts/sentinel2/frmt_sentinel2.html
+++ b/frmts/sentinel2/frmt_sentinel2.html
@@ -7,7 +7,8 @@
 
 <h1>SENTINEL2 -- Sentinel-2 Products</h1>
 
-<p>Driver for Sentinel-2 Level-1B, Level-1C and Level-2A products. (GDAL >= 2.1)</p>
+<p>Driver for Sentinel-2 Level-1B, Level-1C and Level-2A products. (GDAL >= 2.1).
+Starting with GDAL 2.1.3, Level-1C with "Safe Compact" encoding are also supported.</p>
 
 <p>The SENTINEL2 driver will be used if the main metadata .xml file at the
 root of a SENTINEL2 data product is opened (whose name is typically
@@ -85,7 +86,8 @@ All tiles of same resolution and projection are mosaiced together.
 If a product spans over several UTM zones,
 they will be exposed as separate subdatasets.</p>
 
-<p>It is also possible to open the metadata .xml file of each tile, in which case
+<p>It is also possible to open the metadata .xml file of each tile (only for
+original L1C encoding, not supported on "Safe Compact" encoding), in which case
 the driver will typically expose the 4 above mentioned types of sub-datasets.</p>
 
 <h2>Level-2A</h2>
diff --git a/frmts/sentinel2/sentinel2dataset.cpp b/frmts/sentinel2/sentinel2dataset.cpp
index 2d378da..fe3c8e4 100644
--- a/frmts/sentinel2/sentinel2dataset.cpp
+++ b/frmts/sentinel2/sentinel2dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sentinel2dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: sentinel2dataset.cpp 37146 2017-01-14 20:29:26Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Sentinel2 products
@@ -48,7 +48,7 @@
 #define STARTS_WITH_CI(a,b) EQUALN(a,b,strlen(b))
 #endif
 
-CPL_CVSID("$Id: sentinel2dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: sentinel2dataset.cpp 37146 2017-01-14 20:29:26Z rouault $");
 
 CPL_C_START
 // TODO: Leave this declaration while Sentinel2 folks use this as a
@@ -105,6 +105,13 @@ typedef struct
     SENTINEL2_L2A_Tilelocation eLocation;
 } SENTINEL2_L2A_BandDescription;
 
+class L1CSafeCompatGranuleDescription
+{
+public:
+    CPLString osMTDTLPath; // GRANULE/L1C_T30TXT_A007999_20170102T111441/MTD_TL.xml
+    CPLString osBandPrefixPath; // GRANULE/L1C_T30TXT_A007999_20170102T111441/IMG_DATA/T30TXT_20170102T111442_
+};
+
 static const SENTINEL2_L2A_BandDescription asL2ABandDesc[] =
 {
     { "AOT", "Aerosol Optical Thickness map (at 550nm)", TL_IMG_DATA_Rxxm },
@@ -131,6 +138,7 @@ class SENTINEL2GranuleInfo
 {
     public:
         CPLString osPath;
+        CPLString osBandPrefixPath; // for Sentinel 2C SafeCompact
         double    dfMinX, dfMinY, dfMaxX, dfMaxY;
         int       nWidth, nHeight;
 };
@@ -157,10 +165,13 @@ class SENTINEL2Dataset : public VRTDataset
 
         static SENTINEL2Dataset *CreateL1CL2ADataset(
                 SENTINEL2Level eLevel,
+                bool bIsSafeCompact,
                 const std::vector<CPLString>& aosGranuleList,
+                const std::vector<L1CSafeCompatGranuleDescription>& aoL1CSafeCompactGranuleList,
                 std::vector<CPLString>& aosNonJP2Files,
                 int nSubDSPrecision,
                 bool bIsPreview,
+                bool bIsTCI,
                 int nSubDSEPSGCode,
                 bool bAlpha,
                 const std::vector<CPLString>& aosBands,
@@ -363,8 +374,14 @@ int SENTINEL2Dataset::Identify( GDALOpenInfo *poOpenInfo )
     if( STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL2_L2A:") )
         return TRUE;
 
-    /* Accept directly .zip as provided by https://scihub.esa.int/ */
     const char* pszJustFilename = CPLGetFilename(poOpenInfo->pszFilename);
+
+    // We don't handle direct tile access for L1C SafeCompact products
+    // We could, but this isn't just done yet.
+    if( EQUAL( pszJustFilename, "MTD_TL.xml") )
+        return FALSE;
+
+    /* Accept directly .zip as provided by https://scihub.esa.int/ */
     if( (STARTS_WITH_CI(pszJustFilename, "S2A_OPER_PRD_MSI") ||
          STARTS_WITH_CI(pszJustFilename, "S2B_OPER_PRD_MSI") ||
          STARTS_WITH_CI(pszJustFilename, "S2A_USER_PRD_MSI") ||
@@ -2035,6 +2052,84 @@ GDALDataset *SENTINEL2Dataset::OpenL1BSubdataset( GDALOpenInfo * poOpenInfo )
 }
 
 /************************************************************************/
+/*                 SENTINEL2GetGranuleList_L1CSafeCompact()             */
+/************************************************************************/
+
+static bool SENTINEL2GetGranuleList_L1CSafeCompact(CPLXMLNode* psMainMTD,
+                                    const char* pszFilename,
+                                    std::vector<L1CSafeCompatGranuleDescription>& osList)
+{
+    CPLXMLNode* psProductInfo = CPLGetXMLNode(psMainMTD,
+                                "=Level-1C_User_Product.General_Info.Product_Info");
+    if( psProductInfo == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s",
+                        "=Level-1C_User_Product.General_Info.Product_Info");
+        return false;
+    }
+
+    CPLXMLNode* psProductOrganisation =
+                        CPLGetXMLNode(psProductInfo, "Product_Organisation");
+    if( psProductOrganisation == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s", "Product_Organisation");
+        return false;
+    }
+
+    CPLString osDirname( CPLGetDirname(pszFilename) );
+#ifdef HAVE_READLINK
+    char szPointerFilename[2048];
+    int nBytes = static_cast<int>(readlink(pszFilename, szPointerFilename,
+                                           sizeof(szPointerFilename)));
+    if (nBytes != -1)
+    {
+        const int nOffset =
+            std::min(nBytes, static_cast<int>(sizeof(szPointerFilename)-1));
+        szPointerFilename[nOffset] = '\0';
+        osDirname = CPLGetDirname(szPointerFilename);
+    }
+#endif
+
+    const char chSeparator = SENTINEL2GetPathSeparator(osDirname);
+    for(CPLXMLNode* psIter = psProductOrganisation->psChild; psIter != NULL;
+                                                    psIter = psIter->psNext )
+    {
+        if( psIter->eType != CXT_Element ||
+            !EQUAL(psIter->pszValue, "Granule_List") )
+        {
+            continue;
+        }
+        for(CPLXMLNode* psIter2 = psIter->psChild; psIter2 != NULL;
+                                                     psIter2 = psIter2->psNext )
+        {
+            if( psIter2->eType != CXT_Element ||
+                !EQUAL(psIter2->pszValue, "Granule") )
+            {
+                continue;
+            }
+
+            const char* pszImageFile = CPLGetXMLValue(psIter2, "IMAGE_FILE", NULL);
+            if( pszImageFile == NULL || strlen(pszImageFile) < 3 )
+            {
+                CPLDebug("SENTINEL2", "Missing IMAGE_FILE element");
+                continue;
+            }
+            L1CSafeCompatGranuleDescription oDesc;
+            oDesc.osBandPrefixPath = osDirname + chSeparator + pszImageFile;
+            oDesc.osBandPrefixPath.resize( oDesc.osBandPrefixPath.size() - 3 ); // strip B12
+            // GRANULE/L1C_T30TXT_A007999_20170102T111441/IMG_DATA/T30TXT_20170102T111442_B12 -->
+            // GRANULE/L1C_T30TXT_A007999_20170102T111441/MTD_TL.xml
+            oDesc.osMTDTLPath = osDirname + chSeparator +
+                                CPLGetDirname(CPLGetDirname(pszImageFile)) +
+                                chSeparator + "MTD_TL.xml";
+            osList.push_back(oDesc);
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
 /*                           OpenL1C_L2A()                              */
 /************************************************************************/
 
@@ -2064,9 +2159,25 @@ GDALDataset *SENTINEL2Dataset::OpenL1C_L2A( const char* pszFilename,
         return NULL;
     }
 
+    const bool bIsSafeCompact = eLevel == SENTINEL2_L1C &&
+        EQUAL(CPLGetXMLValue(psProductInfo, "Query_Options.PRODUCT_FORMAT", ""),
+              "SAFE_COMPACT");
+
     std::set<int> oSetResolutions;
     std::map<int, std::set<CPLString> > oMapResolutionsToBands;
-    if( eLevel == SENTINEL2_L1C &&
+    if( bIsSafeCompact )
+    {
+        for(unsigned int i = 0; i < NB_BANDS; ++i)
+        {
+            const SENTINEL2BandDescription * psBandDesc = &asBandDesc[i];
+            oSetResolutions.insert( psBandDesc->nResolution );
+            CPLString osName = psBandDesc->pszBandName + 1; /* skip B character */
+            if( atoi(osName) < 10 )
+                osName = "0" + osName;
+            oMapResolutionsToBands[psBandDesc->nResolution].insert(osName);
+        }
+    }
+    else if( eLevel == SENTINEL2_L1C &&
         !SENTINEL2GetResolutionSet(psProductInfo,
                                    oSetResolutions,
                                    oMapResolutionsToBands) )
@@ -2075,7 +2186,21 @@ GDALDataset *SENTINEL2Dataset::OpenL1C_L2A( const char* pszFilename,
     }
 
     std::vector<CPLString> aosGranuleList;
-    if( !SENTINEL2GetGranuleList(psRoot,
+    if( bIsSafeCompact )
+    {
+        std::vector<L1CSafeCompatGranuleDescription> aoL1CSafeCompactGranuleList;
+        if( !SENTINEL2GetGranuleList_L1CSafeCompact(psRoot, pszFilename,
+                                                    aoL1CSafeCompactGranuleList) )
+        {
+            return NULL;
+        }
+        for(size_t i=0;i<aoL1CSafeCompactGranuleList.size();++i)
+        {
+            aosGranuleList.push_back(
+                aoL1CSafeCompactGranuleList[i].osMTDTLPath);
+        }
+    }
+    else if( !SENTINEL2GetGranuleList(psRoot,
                                  eLevel,
                                  pszFilename,
                                  aosGranuleList,
@@ -2156,31 +2281,62 @@ GDALDataset *SENTINEL2Dataset::OpenL1C_L2A( const char* pszFilename,
         }
     }
 
-    /* Expose PREVIEW subdatasets */
-    for(std::set<int>::const_iterator oIterEPSG = oSetEPSGCodes.begin();
-                                    oIterEPSG != oSetEPSGCodes.end();
-                                  ++oIterEPSG )
+    /* Expose TCI or PREVIEW subdatasets */
+    if( bIsSafeCompact )
     {
-        const int nEPSGCode = *oIterEPSG;
-        poDS->GDALDataset::SetMetadataItem(
-            CPLSPrintf("SUBDATASET_%d_NAME", iSubDSNum),
-            CPLSPrintf("%s:%s:PREVIEW:EPSG_%d",
-                        pszPrefix, pszFilename, nEPSGCode),
-            "SUBDATASETS");
+        for(std::set<int>::const_iterator oIterEPSG = oSetEPSGCodes.begin();
+                                        oIterEPSG != oSetEPSGCodes.end();
+                                    ++oIterEPSG )
+        {
+            const int nEPSGCode = *oIterEPSG;
+            poDS->GDALDataset::SetMetadataItem(
+                CPLSPrintf("SUBDATASET_%d_NAME", iSubDSNum),
+                CPLSPrintf("%s:%s:TCI:EPSG_%d",
+                            pszPrefix, pszFilename, nEPSGCode),
+                "SUBDATASETS");
 
-        CPLString osDesc("RGB preview");
-        if( nEPSGCode >= 32601 && nEPSGCode <= 32660 )
-            osDesc += CPLSPrintf(", UTM %dN", nEPSGCode - 32600);
-        else if( nEPSGCode >= 32701 && nEPSGCode <= 32760 )
-            osDesc += CPLSPrintf(", UTM %dS", nEPSGCode - 32700);
-        else
-            osDesc += CPLSPrintf(", EPSG:%d", nEPSGCode);
-        poDS->GDALDataset::SetMetadataItem(
-            CPLSPrintf("SUBDATASET_%d_DESC", iSubDSNum),
-            osDesc.c_str(),
-            "SUBDATASETS");
+            CPLString osDesc("True color image");
+            if( nEPSGCode >= 32601 && nEPSGCode <= 32660 )
+                osDesc += CPLSPrintf(", UTM %dN", nEPSGCode - 32600);
+            else if( nEPSGCode >= 32701 && nEPSGCode <= 32760 )
+                osDesc += CPLSPrintf(", UTM %dS", nEPSGCode - 32700);
+            else
+                osDesc += CPLSPrintf(", EPSG:%d", nEPSGCode);
+            poDS->GDALDataset::SetMetadataItem(
+                CPLSPrintf("SUBDATASET_%d_DESC", iSubDSNum),
+                osDesc.c_str(),
+                "SUBDATASETS");
 
-        iSubDSNum ++;
+            iSubDSNum ++;
+        }
+    }
+    else
+    {
+        for(std::set<int>::const_iterator oIterEPSG = oSetEPSGCodes.begin();
+                                        oIterEPSG != oSetEPSGCodes.end();
+                                    ++oIterEPSG )
+        {
+            const int nEPSGCode = *oIterEPSG;
+            poDS->GDALDataset::SetMetadataItem(
+                CPLSPrintf("SUBDATASET_%d_NAME", iSubDSNum),
+                CPLSPrintf("%s:%s:PREVIEW:EPSG_%d",
+                            pszPrefix, pszFilename, nEPSGCode),
+                "SUBDATASETS");
+
+            CPLString osDesc("RGB preview");
+            if( nEPSGCode >= 32601 && nEPSGCode <= 32660 )
+                osDesc += CPLSPrintf(", UTM %dN", nEPSGCode - 32600);
+            else if( nEPSGCode >= 32701 && nEPSGCode <= 32760 )
+                osDesc += CPLSPrintf(", UTM %dS", nEPSGCode - 32700);
+            else
+                osDesc += CPLSPrintf(", EPSG:%d", nEPSGCode);
+            poDS->GDALDataset::SetMetadataItem(
+                CPLSPrintf("SUBDATASET_%d_DESC", iSubDSNum),
+                osDesc.c_str(),
+                "SUBDATASETS");
+
+            iSubDSNum ++;
+        }
     }
 
     pszNodePath = (eLevel == SENTINEL2_L1C ) ?
@@ -2549,8 +2705,9 @@ GDALDataset *SENTINEL2Dataset::OpenL1C_L2ASubdataset( GDALOpenInfo * poOpenInfo,
 
     const int nSubDSEPSGCode = atoi(pszEPSGCode + 1 + strlen("EPSG_"));
     const bool bIsPreview = STARTS_WITH_CI(pszPrecision + 1, "PREVIEW");
-    const int nSubDSPrecision = (bIsPreview) ? 320 : atoi(pszPrecision + 1);
-    if( !bIsPreview &&
+    const bool bIsTCI = STARTS_WITH_CI(pszPrecision + 1, "TCI");
+    const int nSubDSPrecision = (bIsPreview) ? 320 : (bIsTCI) ? 10 : atoi(pszPrecision + 1);
+    if( !bIsTCI && !bIsPreview &&
         nSubDSPrecision != 10 && nSubDSPrecision != 20 && nSubDSPrecision != 60 )
     {
         CPLError(CE_Failure, CPLE_NotSupported, "Unsupported precision: %d",
@@ -2575,10 +2732,36 @@ GDALDataset *SENTINEL2Dataset::OpenL1C_L2ASubdataset( GDALOpenInfo * poOpenInfo,
     SENTINEL2_CPLXMLNodeHolder oXMLHolder(psRoot);
     CPLStripXMLNamespace(psRoot, NULL, TRUE);
 
+    const bool bIsSafeCompact = eLevel == SENTINEL2_L1C &&
+        EQUAL(CPLGetXMLValue(psRoot,
+                "=Level-1C_User_Product.General_Info.Product_Info.Query_Options.PRODUCT_FORMAT", ""),
+              "SAFE_COMPACT");
+
     std::vector<CPLString> aosGranuleList;
-    std::set<int> oSetResolutions;
     std::map<int, std::set<CPLString> > oMapResolutionsToBands;
-    if( !SENTINEL2GetGranuleList(psRoot,
+    std::vector<L1CSafeCompatGranuleDescription> aoL1CSafeCompactGranuleList;
+    if( bIsSafeCompact )
+    {
+        for(unsigned int i = 0; i < NB_BANDS; ++i)
+        {
+            const SENTINEL2BandDescription * psBandDesc = &asBandDesc[i];
+            CPLString osName = psBandDesc->pszBandName + 1; /* skip B character */
+            if( atoi(osName) < 10 )
+                osName = "0" + osName;
+            oMapResolutionsToBands[psBandDesc->nResolution].insert(osName);
+        }
+        if( !SENTINEL2GetGranuleList_L1CSafeCompact(psRoot, osFilename,
+                                                    aoL1CSafeCompactGranuleList) )
+        {
+            return NULL;
+        }
+        for(size_t i=0;i<aoL1CSafeCompactGranuleList.size();++i)
+        {
+            aosGranuleList.push_back(
+                aoL1CSafeCompactGranuleList[i].osMTDTLPath);
+        }
+    }
+    else if( !SENTINEL2GetGranuleList(psRoot,
                                  eLevel,
                                  osFilename,
                                  aosGranuleList,
@@ -2591,13 +2774,13 @@ GDALDataset *SENTINEL2Dataset::OpenL1C_L2ASubdataset( GDALOpenInfo * poOpenInfo,
 
     std::vector<CPLString> aosBands;
     std::set<CPLString> oSetBands;
-    if( bIsPreview )
+    if( bIsPreview || bIsTCI )
     {
         aosBands.push_back("04");
         aosBands.push_back("03");
         aosBands.push_back("02");
     }
-    else if( eLevel == SENTINEL2_L1C )
+    else if( eLevel == SENTINEL2_L1C && !bIsSafeCompact )
     {
         CPLXMLNode* psBandList = CPLGetXMLNode(psRoot,
             "=Level-1C_User_Product.General_Info.Product_Info.Query_Options.Band_List");
@@ -2672,10 +2855,13 @@ GDALDataset *SENTINEL2Dataset::OpenL1C_L2ASubdataset( GDALOpenInfo * poOpenInfo,
         CPLTestBool(SENTINEL2GetOption(poOpenInfo, "ALPHA", "FALSE"));
 
     SENTINEL2Dataset* poDS = CreateL1CL2ADataset(eLevel,
+                                                 bIsSafeCompact,
                                                  aosGranuleList,
+                                                 aoL1CSafeCompactGranuleList,
                                                  aosNonJP2Files,
                                                  nSubDSPrecision,
                                                  bIsPreview,
+                                                 bIsTCI,
                                                  nSubDSEPSGCode,
                                                  bAlpha,
                                                  aosBands,
@@ -2711,6 +2897,9 @@ GDALDataset *SENTINEL2Dataset::OpenL1C_L2ASubdataset( GDALOpenInfo * poOpenInfo,
     if( bIsPreview )
         osOverviewFile = CPLSPrintf("%s_PREVIEW_EPSG_%d.tif.ovr",
                                     osFilename.c_str(), nSubDSEPSGCode);
+    else if( bIsTCI )
+        osOverviewFile = CPLSPrintf("%s_TCI_EPSG_%d.tif.ovr",
+                                    osFilename.c_str(), nSubDSEPSGCode);
     else
         osOverviewFile = CPLSPrintf("%s_%dm_EPSG_%d.tif.ovr",
                                     osFilename.c_str(), nSubDSPrecision,
@@ -2833,10 +3022,13 @@ void SENTINEL2Dataset::AddL1CL2ABandMetadata(SENTINEL2Level eLevel,
 
 SENTINEL2Dataset* SENTINEL2Dataset::CreateL1CL2ADataset(
                 SENTINEL2Level eLevel,
+                bool bIsSafeCompact,
                 const std::vector<CPLString>& aosGranuleList,
+                const std::vector<L1CSafeCompatGranuleDescription>& aoL1CSafeCompactGranuleList,
                 std::vector<CPLString>& aosNonJP2Files,
                 int nSubDSPrecision,
                 bool bIsPreview,
+                bool bIsTCI,
                 int nSubDSEPSGCode, /* or -1 if not known at this point */
                 bool bAlpha,
                 const std::vector<CPLString>& aosBands,
@@ -2848,7 +3040,14 @@ SENTINEL2Dataset* SENTINEL2Dataset::CreateL1CL2ADataset(
     /* and the location of each granule */
     double dfMinX = 1e20, dfMinY = 1e20, dfMaxX = -1e20, dfMaxY = -1e20;
     std::vector<SENTINEL2GranuleInfo> aosGranuleInfoList;
-    const int nDesiredResolution = (bIsPreview) ? 0 : nSubDSPrecision;
+    const int nDesiredResolution = (bIsPreview || bIsTCI) ? 0 : nSubDSPrecision;
+
+    if( bIsSafeCompact )
+    {
+        CPLAssert( aosGranuleList.size() ==
+                   aoL1CSafeCompactGranuleList.size() );
+    }
+
     for(size_t i=0;i<aosGranuleList.size();i++)
     {
         int nEPSGCode = 0;
@@ -2877,6 +3076,11 @@ SENTINEL2Dataset* SENTINEL2Dataset::CreateL1CL2ADataset(
 
             SENTINEL2GranuleInfo oGranuleInfo;
             oGranuleInfo.osPath = CPLGetPath(aosGranuleList[i]);
+            if( bIsSafeCompact )
+            {
+                oGranuleInfo.osBandPrefixPath =
+                            aoL1CSafeCompactGranuleList[i].osBandPrefixPath;
+            }
             oGranuleInfo.dfMinX = dfULX;
             oGranuleInfo.dfMinY = dfLRY;
             oGranuleInfo.dfMaxX = dfLRX;
@@ -2924,14 +3128,14 @@ SENTINEL2Dataset* SENTINEL2Dataset::CreateL1CL2ADataset(
     adfGeoTransform[5] = -nSubDSPrecision;
     poDS->SetGeoTransform(adfGeoTransform);
     poDS->GDALDataset::SetMetadataItem("COMPRESSION", "JPEG2000", "IMAGE_STRUCTURE");
-    if( bIsPreview )
+    if( bIsPreview || bIsTCI )
         poDS->GDALDataset::SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
 
-    int nBits = (bIsPreview) ? 8 : 0 /* 0 = unknown yet*/;
-    int nValMax = (bIsPreview) ? 255 : 0 /* 0 = unknown yet*/;
-    const int nBands = (bIsPreview) ? 3 : ((bAlpha) ? 1 : 0) + static_cast<int>(aosBands.size());
-    const int nAlphaBand = (bIsPreview || !bAlpha) ? 0 : nBands;
-    const GDALDataType eDT = (bIsPreview) ? GDT_Byte: GDT_UInt16;
+    int nBits = (bIsPreview || bIsTCI) ? 8 : 0 /* 0 = unknown yet*/;
+    int nValMax = (bIsPreview || bIsTCI) ? 255 : 0 /* 0 = unknown yet*/;
+    const int nBands = (bIsPreview || bIsTCI) ? 3 : ((bAlpha) ? 1 : 0) + static_cast<int>(aosBands.size());
+    const int nAlphaBand = (bIsPreview || bIsTCI || !bAlpha) ? 0 : nBands;
+    const GDALDataType eDT = (bIsPreview || bIsTCI) ? GDT_Byte: GDT_UInt16;
 
     std::map<CPLString, GDALProxyPoolDataset*> oMapPVITile;
 
@@ -2970,12 +3174,35 @@ SENTINEL2Dataset* SENTINEL2Dataset::CreateL1CL2ADataset(
         for(size_t iSrc=0;iSrc<aosGranuleInfoList.size();iSrc++)
         {
             const SENTINEL2GranuleInfo& oGranuleInfo = aosGranuleInfoList[iSrc];
-            CPLString osTile(SENTINEL2GetTilename(
-                    oGranuleInfo.osPath,
-                    CPLGetFilename(oGranuleInfo.osPath),
-                    osBandName,
-                    bIsPreview,
-                    (eLevel == SENTINEL2_L1C) ? 0 : nSubDSPrecision));
+            CPLString osTile;
+
+            if( bIsSafeCompact )
+            {
+                if( bIsTCI )
+                {
+                    osTile = oGranuleInfo.osBandPrefixPath + "TCI.jp2";
+                }
+                else
+                {
+                    osTile = oGranuleInfo.osBandPrefixPath + "B";
+                    if( osBandName.size() == 1 )
+                        osTile += "0" + osBandName;
+                    else if( osBandName.size() == 3 )
+                        osTile += osBandName.substr(1);
+                    else
+                        osTile += osBandName;
+                    osTile += ".jp2";
+                }
+            }
+            else
+            {
+                osTile = SENTINEL2GetTilename(
+                        oGranuleInfo.osPath,
+                        CPLGetFilename(oGranuleInfo.osPath),
+                        osBandName,
+                        bIsPreview,
+                        (eLevel == SENTINEL2_L1C) ? 0 : nSubDSPrecision);
+            }
 
             bool bTileFound = false;
             if( nValMax == 0 )
@@ -3153,10 +3380,13 @@ GDALDataset* SENTINEL2Dataset::OpenL1CTileSubdataset( GDALOpenInfo * poOpenInfo
 
     std::vector<CPLString> aosNonJP2Files;
     SENTINEL2Dataset* poDS = CreateL1CL2ADataset(SENTINEL2_L1C,
+                                                 false, // bIsSafeCompact
                                                  aosGranuleList,
+                                                 std::vector<L1CSafeCompatGranuleDescription>(),
                                                  aosNonJP2Files,
                                                  nSubDSPrecision,
                                                  bIsPreview,
+                                                 false, // bIsTCI
                                                  -1 /*nSubDSEPSGCode*/,
                                                  bAlpha,
                                                  aosBands,
diff --git a/frmts/vrt/vrtsources.cpp b/frmts/vrt/vrtsources.cpp
index cbc7881..cac84ce 100644
--- a/frmts/vrt/vrtsources.cpp
+++ b/frmts/vrt/vrtsources.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtsources.cpp 35369 2016-09-08 09:33:26Z rouault $
+ * $Id: vrtsources.cpp 36800 2016-12-11 22:24:27Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTSimpleSource, VRTFuncSource and
@@ -43,7 +43,7 @@
 #define isnan std::isnan
 #endif
 
-CPL_CVSID("$Id: vrtsources.cpp 35369 2016-09-08 09:33:26Z rouault $");
+CPL_CVSID("$Id: vrtsources.cpp 36800 2016-12-11 22:24:27Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -2408,6 +2408,16 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
     return CE_None;
 }
 
+// Explicitly instantiate template method, as it is used in another file.
+template
+CPLErr VRTComplexSource::RasterIOInternal<float>( int nReqXOff, int nReqYOff,
+                                    int nReqXSize, int nReqYSize,
+                                    void *pData, int nOutXSize, int nOutYSize,
+                                    GDALDataType eBufType,
+                                    GSpacing nPixelSpace, GSpacing nLineSpace,
+                                    GDALRasterIOExtraArg* psExtraArg,
+                                    GDALDataType eWrkDataType );
+
 /************************************************************************/
 /*                             GetMinimum()                             */
 /************************************************************************/
diff --git a/gcore/gdal_version.h b/gcore/gdal_version.h
index 3e4aa05..a486be4 100644
--- a/gcore/gdal_version.h
+++ b/gcore/gdal_version.h
@@ -6,7 +6,7 @@
 #ifndef GDAL_VERSION_MAJOR
 #  define GDAL_VERSION_MAJOR    2
 #  define GDAL_VERSION_MINOR    1
-#  define GDAL_VERSION_REV      2
+#  define GDAL_VERSION_REV      3
 #  define GDAL_VERSION_BUILD    0
 #endif
 
@@ -22,8 +22,8 @@
 #endif
 
 #ifndef GDAL_RELEASE_DATE
-#  define GDAL_RELEASE_DATE     20161024
+#  define GDAL_RELEASE_DATE     20172001
 #endif
 #ifndef GDAL_RELEASE_NAME
-#  define GDAL_RELEASE_NAME     "2.1.2"
+#  define GDAL_RELEASE_NAME     "2.1.3"
 #endif
diff --git a/makefile.vc b/makefile.vc
index 129ed93..3586315 100644
--- a/makefile.vc
+++ b/makefile.vc
@@ -88,7 +88,7 @@ clean:
 	cd ogr
 	$(MAKE) /f makefile.vc allclean
 	cd ..
-    cd gnm
+	cd gnm
 	$(MAKE) /f makefile.vc allclean
 	cd ..
 	cd apps
@@ -159,9 +159,9 @@ ogr_dir:      port_dir
 	cd ..
 
 gnm_dir:      ogr_dir
-    cd gnm
-    $(MAKE) /f makefile.vc gnm.lib frmts
-    cd ..
+	cd gnm
+	$(MAKE) /f makefile.vc gnm.lib frmts
+	cd ..
 
 lib_dist:	default
 	rm -rf $(DISTDIR)
@@ -173,7 +173,7 @@ $(GDAL_DLL): staticlib
 	link /nologo /dll $(OGR_INCLUDE) $(BASE_INCLUDE) $(LIBOBJ) \
 		$(EXTERNAL_LIBS) gcore\Version.res \
 		 /out:$(GDAL_DLL) /implib:gdal_i.lib $(LINKER_FLAGS)
-    if exist $(GDAL_DLL).manifest mt -manifest $(GDAL_DLL).manifest -outputresource:$(GDAL_DLL);2
+	if exist $(GDAL_DLL).manifest mt -manifest $(GDAL_DLL).manifest -outputresource:$(GDAL_DLL);2
 
 dll:	$(GDAL_DLL)
 
diff --git a/makegdal_gen.bat b/makegdal_gen.bat
index 97d7886..40a984e 100644
--- a/makegdal_gen.bat
+++ b/makegdal_gen.bat
@@ -5,8 +5,8 @@
 :: 
 ::  Name:     makegdal_gen.bat
 ::  Project:  GDAL 
-::  Purpose:  Generate MS Visual Studio 2003...N project files    
-::  Author:   Ivan Lucena, [lucena_ivan at hotmail.com]
+::  Purpose:  Generate MS Visual C++ => 10.0 project files    
+::  Author:   Ivan Lucena, [ivan lucena at outlook dot com]
 :: 
 :: ****************************************************************************
 ::  Copyright (c) 2007, Ivan Lucena    
@@ -30,121 +30,255 @@
 ::  DEALINGS IN THE SOFTWARE.
 :: ****************************************************************************
 
-::  *********************
-::  Usage
-::  *********************
-
 if "%1"=="" (
-    echo Usage: makegdal_gen "MS Visual C++ version" "platform{32,64}" ^> makegdalNN.vcproj
-    echo Examples:
-    echo    makegdal_gen  7.10 32 ^> makegdal71.vcproj
-    echo    makegdal_gen  8.00 64 ^> makegdal80.vcproj
-    echo    makegdal_gen  9.00 64 ^> makegdal90.vcproj
-    echo    makegdal_gen 10.00 64 ^> makegdal10.vcproj
-    goto :end
+   goto :usage
+)
+
+if "%2"=="" (
+   goto :usage
+)
+
+if "%3"=="" (
+   goto :usage
 )
 
 ::  *********************
-::  Get platform 32 or 64
+::  Get Visual C++ version
 ::  *********************
 
-set _plat_=%2
+set _vcver_=%1
 
-if "%_plat_%"=="" (
-    set _plat_=32
-)
+set _clver_=1600
 
-if "%_plat_%"=="32" (
-    set _plat_=Win32
+if "%_vcver_%"=="14.0" (
+	set _clver_=1900
+) else ( if "%_vcver_%"=="12.0" (
+	set _clver_=1800
+) else ( if "%_vcver_%"=="11.0" (
+	set _clver_=1700
+) else ( if "%_vcver_%"=="10.0" (
+	set _clver_=1600
 ) else (
-    set _plat_=x64
-)
+    echo Wrong value for parameter 1. See usage:
+	goto :usage
+))))
 
 ::  *********************
-::  Get Visual C++ version
+::  Get Platform
 ::  *********************
 
-set _vcver_=%1
-set _clver_=1310
+set _platf_=%2
+set _winver_=Win32
 
-if "%_vcver_%"=="6.00" (
-	set _clver_=1200
-)
-if "%_vcver_%"=="7.00" (
-	set _clver_=1300
+if not "%_platf_%"=="32" (
+    if not "%_platf_%"=="64" (
+	    echo Wrong value for parameter 2. See usage:
+	    goto :usage
+    )
 )
-if "%_vcver_%"=="7.10" (
-	set _clver_=1310
+
+if "%_platf_%"=="64" (
+    set _winver_=x64
 )
-if "%_vcver_%"=="8.00" (
-	set _clver_=1400
+
+goto :continue
+
+::  *********************
+:usage
+::  *********************
+
+echo Usage: makegdal_gen ^<Visual C++ version^> [32^|64] ^<^(*^) project file name^>
+echo Parameters:
+echo    1 : Visual C++ version is not the same as Visual Studio version ^( =^> 10.0 ^)
+echo    2 : Windows platform 32 for Win32 and 64 for Win64
+echo    3 : Base file name, with no path and no extension ^(*^)
+echo Examples:
+echo    makegdal_gen 10.1 32 makefileproj_vs10
+echo    makegdal_gen 11.0 64 makefileproj_vs11
+echo    makegdal_gen 12.0 64 makefileproj_vs12
+echo    makegdal_gen 14.0 64 makefileproj_vs14
+
+goto :end
+
+::  *********************
+::  Set Project file names
+::  *********************
+
+:continue
+
+set _mainfile_=%CD%\%3.vcxproj
+set _userfile_=%_mainfile_%.user
+set _ftrlfile_=%_mainfile_%.filters
+
+:: Add quotes
+
+set _mainfile_="%_mainfile_%"
+set _userfile_="%_userfile_%"
+set _ftrlfile_="%_ftrlfile_%"
+
+:: Progress message
+
+echo Generating:
+echo   %_mainfile_%
+echo   %_userfile_%
+echo   %_ftrlfile_%
+echo This might take a little while...
+
+:: Delete existing files
+
+if exist %_mainfile_% (
+  del %_mainfile_%
 )
-if "%_vcver_%"=="9.00" (
-	set _clver_=1500
+
+if exist %_userfile_% ( 
+  del %_userfile_%
 )
-if "%_vcver_%"=="10.00" (
-	set _vcver_=9.00
-	set _clver_=1600
+
+if exist %_ftrlfile_% ( 
+  del %_ftrlfile_%
 )
 
-::  *********************
-::  Get GDAL Version
-::  *********************
+:: **********************************************
+:: Generate user file (.vcxproj.user)
+:: **********************************************
+
+echo ^<?xml version="1.0" encoding="utf-8"?^>                   >> %_userfile_%
+echo ^<Project ToolsVersion="%_vcver_%" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"^>   >> %_userfile_%
+echo     ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|%_winver_%'"^>  >> %_userfile_%
+echo       ^<LocalDebuggerDebuggerType^>Auto^</LocalDebuggerDebuggerType^>                 >> %_userfile_%
+echo       ^<LocalDebuggerCommand^>%CD%\apps\gdal_translate.exe^</LocalDebuggerCommand^>   >> %_userfile_%
+echo       ^<LocalDebuggerCommandArguments^>--formats^</LocalDebuggerCommandArguments^>    >> %_userfile_%
+echo       ^<DebuggerFlavor^>WindowsLocalDebugger^</DebuggerFlavor^>                       >> %_userfile_%
+echo     ^</PropertyGroup^>                                     >> %_userfile_%
+echo ^</Project^>                                               >> %_userfile_%
 
-for /f %%v in (VERSION) do set _gdalver_=%%v
-set _gdalnum_=%_gdalver_:.=%
-set _gdalnum_=%_gdalnum_:~0,2%
+:: **********************************************
+:: Initialize filters file (.vcxproj.filters)
+:: **********************************************
+
+echo ^<?xml version="1.0" encoding="utf-8"?^>                   >> %_ftrlfile_%
+echo ^<Project ToolsVersion="5.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"^>         >> %_ftrlfile_%
 
 :: **********************************************
-:: Main file generator
+:: Main file generator (.vcxproj) and filters file (.vcxproj.filters)
 :: **********************************************
 
-echo ^<?xml version="1.0" encoding="Windows-1252"?^>
-echo ^<VisualStudioProject            
-echo 	ProjectType="Visual C++"
-echo 	Version="%_vcver_%"
-echo 	Name="makegdal%_vcnum_%"
-echo 	ProjectGUID="{769DD10E-E284-46BE-9172-A35184250A3A}"
-echo 	Keyword="MakeFileProj"^>
-echo 	^<Platforms^>
-echo 		^<Platform Name="%_plat_%"/^>
-echo 	^</Platforms^>
-echo 	^<Configurations^>
-echo 		^<Configuration
-echo 			Name="Debug|%_plat_%"
-echo 			OutputDirectory="$(ConfigurationName)"
-echo 			IntermediateDirectory="$(ConfigurationName)"
-echo 			ConfigurationType="0"^>
-echo 			^<Tool
-echo 				Name="VCNMakeTool"
-echo 				BuildCommandLine=  ^"cd $(ProjectDir) ^&^& nmake -f makefile.vc ^&^& nmake -f makefile.vc install^"
-echo 				ReBuildCommandLine=^"cd $(ProjectDir) ^&^& nmake -f makefile.vc clean^ ^&^& nmake -f makefile.vc ^&^& nmake -f makefile.vc install^"
-echo 				CleanCommandLine=  ^"cd $(ProjectDir) ^&^& nmake -f makefile.vc clean^"
-echo 				Output="gdal%_gdalnum_%.dll"/^>
-echo 		^</Configuration^>
-echo 		^<Configuration
-echo 			Name="Release|%_plat_%"
-echo 			OutputDirectory="$(ConfigurationName)"
-echo 			IntermediateDirectory="$(ConfigurationName)"
-echo 			ConfigurationType="0"^>
-echo 			^<Tool
-echo 				Name="VCNMakeTool"
-echo 				BuildCommandLine=  ^"cd $(ProjectDir) ^&^& nmake -f makefile.vc ^&^& nmake -f makefile.vc install^"
-echo 				ReBuildCommandLine=^"cd $(ProjectDir) ^&^& nmake -f makefile.vc clean^ ^&^& nmake -f makefile.vc ^&^& nmake -f makefile.vc install^"
-echo 				CleanCommandLine=  ^"cd $(ProjectDir) ^&^& nmake -f makefile.vc clean^"
-echo 				Output="gdal%_gdalnum_%.dll"/^>
-echo 		^</Configuration^>
-echo 	^</Configurations^>
-echo 	^<References^>
-echo 	^</References^>
-echo 	^<Files^>
-call :create_filter . "*.vc;*.opt;*.local" "Make Files"    "	"
-call :create_filter . "*.h"                "Include Files" "	"
-call :create_filter . "*.c;*.cpp"          "Source Files"  "	"
-echo 	^</Files^>
-echo 	^<Globals^>
-echo 	^</Globals^>
-echo ^</VisualStudioProject^>
+echo ^<?xml version="1.0" encoding="utf-8"?^>                   >> %_mainfile_%
+echo ^<Project DefaultTargets="Build" ToolsVersion="%_vcver_%" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"^>          >> %_mainfile_%
+echo   ^<ItemGroup Label="ProjectConfigurations"^>              >> %_mainfile_%
+echo     ^<ProjectConfiguration Include="Debug|%_winver_%"^>    >> %_mainfile_%
+echo       ^<Configuration^>Debug^</Configuration^>             >> %_mainfile_%
+echo       ^<Platform^>%_winver_%^</Platform^>                  >> %_mainfile_%
+echo     ^</ProjectConfiguration^>                              >> %_mainfile_%
+echo     ^<ProjectConfiguration Include="Release|%_winver_%"^>  >> %_mainfile_%
+echo       ^<Configuration^>Release^</Configuration^>           >> %_mainfile_%
+echo       ^<Platform^>%_winver_%^</Platform^>                  >> %_mainfile_%
+echo     ^</ProjectConfiguration^>                              >> %_mainfile_%
+echo   ^</ItemGroup^>                                           >> %_mainfile_% 
+echo   ^<PropertyGroup Label="Globals"^>                        >> %_mainfile_%
+echo     ^<Keyword^>MakeFileProj^</Keyword^>                    >> %_mainfile_%
+echo   ^</PropertyGroup^>                                       >> %_mainfile_%
+echo   ^<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /^>  >> %_mainfile_%   
+echo   ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|%_winver_%'" Label="Configuration"^>    >> %_mainfile_%
+echo     ^<ConfigurationType^>Makefile^</ConfigurationType^>    >> %_mainfile_%
+echo     ^<UseDebugLibraries^>true^</UseDebugLibraries^>        >> %_mainfile_%
+echo     ^<PlatformToolset^>v120^</PlatformToolset^>            >> %_mainfile_%
+echo   ^</PropertyGroup^>                                       >> %_mainfile_%
+echo   ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|%_winver_%'" Label="Configuration"^>  >> %_mainfile_%
+echo     ^<ConfigurationType^>Makefile^</ConfigurationType^>    >> %_mainfile_%
+echo     ^<UseDebugLibraries^>true^</UseDebugLibraries^>        >> %_mainfile_%
+echo     ^<PlatformToolset^>v120^</PlatformToolset^>            >> %_mainfile_%
+echo   ^</PropertyGroup^>                                       >> %_mainfile_%
+echo   ^<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /^>      >> %_mainfile_%
+echo   ^<ImportGroup Label="ExtensionSettings"^>                >> %_mainfile_%  
+echo   ^</ImportGroup^>                                         >> %_mainfile_%
+echo   ^<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|%_winver_%'"^>     >> %_mainfile_% 
+echo     ^<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /^>    >> %_mainfile_%
+echo   ^</ImportGroup^>                                         >> %_mainfile_%
+echo   ^<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|%_winver_%'"^>  >> %_mainfile_%
+echo     ^<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /^>     >> %_mainfile_%
+echo   ^</ImportGroup^>                                         >> %_mainfile_%
+echo   ^<PropertyGroup Label="UserMacros" /^>                   >> %_mainfile_%
+echo   ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|%_winver_%'"^>     >> %_mainfile_%
+echo     ^<NMakeBuildCommandLine^>nmake -f makefile.vc^</NMakeBuildCommandLine^>            >> %_mainfile_%
+echo     ^<NMakeOutput^>^</NMakeOutput^>                                                    >> %_mainfile_%
+echo     ^<NMakeCleanCommandLine^>nmake -f makefile.vc clean^</NMakeCleanCommandLine^>      >> %_mainfile_%
+echo     ^<NMakeReBuildCommandLine^>nmake -f makefile.vc clean ^&^& nmake -f makefile.vc^</NMakeReBuildCommandLine^>  >> %_mainfile_%
+echo     ^<NMakePreprocessorDefinitions^>%_winver_%;_DEBUG;$(NMakePreprocessorDefinitions)^</NMakePreprocessorDefinitions^>   >> %_mainfile_%
+echo     ^<LibraryPath^>$(VC_LibraryPath_x%_platf_%);$(WindowsSDK_LibraryPath_x%_platf_%);$(VC_SourcePath);^</LibraryPath^>   >> %_mainfile_%
+echo   ^</PropertyGroup^>                                                                   >> %_mainfile_%
+echo   ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|%_winver_%'"^>   >> %_mainfile_%
+echo     ^<NMakeBuildCommandLine^>nmake -f makefile.vc^</NMakeBuildCommandLine^>            >> %_mainfile_%
+echo     ^<NMakeOutput^>^</NMakeOutput^>                                                    >> %_mainfile_%
+echo     ^<NMakeCleanCommandLine^>nmake -f makefile.vc clean^</NMakeCleanCommandLine^>      >> %_mainfile_%
+echo     ^<NMakeReBuildCommandLine^>nmake -f makefile.vc clean ^&^& nmake -f makefile.vc^</NMakeReBuildCommandLine^>  >> %_mainfile_%
+echo     ^<NMakePreprocessorDefinitions^>%_winver_%;NDEBUG;$(NMakePreprocessorDefinitions)^</NMakePreprocessorDefinitions^>   >> %_mainfile_%
+echo     ^<LibraryPath^>$(VC_LibraryPath_x%_platf_%);$(WindowsSDK_LibraryPath_x%_platf_%);$(VC_SourcePath);^</LibraryPath^>   >> %_mainfile_%
+echo   ^</PropertyGroup^>                                                                   >> %_mainfile_%
+echo   ^<ItemDefinitionGroup^>                                  >> %_mainfile_%
+echo   ^</ItemDefinitionGroup^>                                 >> %_mainfile_%
+
+:: create a root path with nmake files
+
+echo   ^<ItemGroup^>                                            >> %_mainfile_%
+echo       ^<Test Include="nmake.local" /^>                     >> %_mainfile_%
+echo       ^<Test Include="nmake.opt" /^>                       >> %_mainfile_%
+echo   ^</ItemGroup^>                                           >> %_mainfile_%
+
+echo   ^<ItemGroup^>                                            >> %_ftrlfile_%
+echo       ^<Test Include="nmake.local" /^>                     >> %_ftrlfile_%
+echo       ^<Test Include="nmake.opt" /^>                       >> %_ftrlfile_%
+echo   ^</ItemGroup^>                                           >> %_ftrlfile_%
+
+:: create filters only
+
+echo   ^<ItemGroup^>                                            >> %_ftrlfile_%
+call :create_filter . "*.vc;" 1 "Make Files" "None"
+call :create_filter . "*.h;*.hpp" 1 "Include Files" "ClInclude"
+call :create_filter . "*.c;*.cpp" 1 "Source Files" "ClCompile"
+echo   ^</ItemGroup^>                                           >> %_ftrlfile_%
+
+:: create main file and links to filters
+
+echo   ^<ItemGroup^>                                            >> %_mainfile_%
+echo   ^<ItemGroup^>                                            >> %_ftrlfile_%
+call :create_filter . "*.vc" 0 "Make Files" "None"
+echo   ^</ItemGroup^>                                           >> %_mainfile_%
+echo   ^</ItemGroup^>                                           >> %_ftrlfile_%
+
+echo   ^<ItemGroup^>                                            >> %_mainfile_%
+echo   ^<ItemGroup^>                                            >> %_ftrlfile_%
+call :create_filter . "*.h;*.hpp" 0 "Include Files" "ClInclude"
+echo   ^</ItemGroup^>                                           >> %_mainfile_%
+echo   ^</ItemGroup^>                                           >> %_ftrlfile_%
+
+echo   ^<ItemGroup^>                                            >> %_mainfile_%
+echo   ^<ItemGroup^>                                            >> %_ftrlfile_%
+call :create_filter . "*.c;*.cpp" 0 "Source Files" "ClCompile"
+echo   ^</ItemGroup^>                                           >> %_mainfile_%
+echo   ^</ItemGroup^>                                           >> %_ftrlfile_%
+
+:: **********************************************
+:: Finalize projects 
+:: **********************************************
+
+echo ^</Project^>                                               >> %_ftrlfile_%
+
+echo   ^<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/^>  >> %_mainfile_%
+echo ^</Project^>                                               >> %_mainfile_%
+
+echo Done!
+echo Edit nmake.local or nmake.opt:
+echo MSVCVER=%_clver_%
+if "%_platf_%"=="64" (
+    echo WIN64=YES
+) else (
+    echo #WIN64=YES
+)
+
+:: **********************************************
+:: The end
+:: **********************************************
 
 goto :end
 
@@ -154,65 +288,82 @@ goto :end
 
     set _path_=%1
     set _mask_=%2
-    set _name_=%3
-    set _tabs_="	"%4
-    set _next_="	"%_tabs_%
+    set _fonly_=%3
+    set _name_=%4
+    set _item_=%5
     
     ::  *********************
-    ::  remove quotes 
+    ::  Remove quotes 
     ::  *********************
     
     set _name_=%_name_:"=%
     set _mask_=%_mask_:"=% 
-    set _tabs_=%_tabs_:"=%
-    set _next_=%_next_:"=%
-    
+    set _fonly_=%_fonly_:"=%
+    set _item_=%_item_:"=%
+  
     ::  *********************
-    ::  stop folders
+    ::  Stop folders
     ::  *********************
     
-    for %%d in (data debian docs html m4 pymod swig vb6) do (
-        if "%_name_%"=="%%d" (
+    set _folder_=%~nx1
+  
+    for %%d in (data debian docs html m4 pymod swig bridge vb6) do (
+        if "%_folder_%"=="%%d" (
             goto :end
         )
     )
 
     ::  *********************
-    ::  check whole folder tree
+    ::  Check if a folde is empty
     ::  *********************
+
+    set _find_=1
     
+    for /R %%f in (%_mask_%) do (
+      goto :not_empty
+    )
+
     set _find_=0
-    for /R %%f in (%_mask_%) do set _find_=1    
+  
+    :not_empty
+  
     if %_find_%==0 (
         goto :end
     )
 
     ::  *********************
-    ::  create filter 
+    ::  Add filters 
     ::  *********************
     
-    echo %_tabs_%^<Filter Name="%_name_%" Filter="%_mask_%"^>
-    
+    if %_fonly_%==1 (
+        echo     ^<Filter Include="%_name_%"^>                   >> %_ftrlfile_%
+        echo       ^<Extensions^>%_mask_%^</Extensions^>         >> %_ftrlfile_%
+        echo     ^</Filter^>                                     >> %_ftrlfile_%
+    )
+  
     ::  *********************
-    ::  add files
+    ::  Add files
     ::  *********************
     
-    for %%f in (%_mask_%) do (
-        echo %_next_%^<File RelativePath="%_path_%\%%f" /^>
+    if %_fonly_%==0 (
+        for %%f in (%_mask_%) do (
+            echo     ^<%_item_% Include="%_path_%\%%f"/^>        >> %_mainfile_%
+            echo     ^<%_item_% Include="%_path_%\%%f"^>         >> %_ftrlfile_%
+            echo       ^<Filter^>%_name_%^</Filter^>             >> %_ftrlfile_%
+            echo     ^</%_item_%^>                               >> %_ftrlfile_% 
+        )
     )
-    
+  
     ::  *********************
-    ::  clib all the branches
+    ::  Clib all the branches recursivelly
     ::  *********************
     
     for /D %%d in (*) do (
         cd %%d
-        call :create_filter %_path_%\%%d "%_mask_%" %%d "%_tabs_%"
+        call :create_filter %_path_%\%%d "%_mask_%" %_fonly_% "%_name_%\%%d" %_item_%
         cd ..
     )
     
-    echo %_tabs_%^</Filter^>
-
 :: **********************************************
 :end
 :: **********************************************
diff --git a/man/man1/gdal-config.1 b/man/man1/gdal-config.1
index cd732bb..c02263b 100644
--- a/man/man1/gdal-config.1
+++ b/man/man1/gdal-config.1
@@ -1,4 +1,4 @@
-.TH "gdal-config" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal-config" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal2tiles.1 b/man/man1/gdal2tiles.1
index 5f5612e..edbd4fe 100644
--- a/man/man1/gdal2tiles.1
+++ b/man/man1/gdal2tiles.1
@@ -1,4 +1,4 @@
-.TH "gdal2tiles" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal2tiles" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_calc.1 b/man/man1/gdal_calc.1
index d0ae25d..aeefc6a 100644
--- a/man/man1/gdal_calc.1
+++ b/man/man1/gdal_calc.1
@@ -1,4 +1,4 @@
-.TH "gdal_calc" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_calc" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_contour.1 b/man/man1/gdal_contour.1
index 854a973..fd146b3 100644
--- a/man/man1/gdal_contour.1
+++ b/man/man1/gdal_contour.1
@@ -1,4 +1,4 @@
-.TH "gdal_contour" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_contour" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_edit.1 b/man/man1/gdal_edit.1
index 358b55a..3635a54 100644
--- a/man/man1/gdal_edit.1
+++ b/man/man1/gdal_edit.1
@@ -1,4 +1,4 @@
-.TH "gdal_edit" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_edit" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_fillnodata.1 b/man/man1/gdal_fillnodata.1
index 4ecfb43..b1b55d3 100644
--- a/man/man1/gdal_fillnodata.1
+++ b/man/man1/gdal_fillnodata.1
@@ -1,4 +1,4 @@
-.TH "gdal_fillnodata" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_fillnodata" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_grid.1 b/man/man1/gdal_grid.1
index de73ac4..32e0d74 100644
--- a/man/man1/gdal_grid.1
+++ b/man/man1/gdal_grid.1
@@ -1,4 +1,4 @@
-.TH "gdal_grid" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_grid" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_merge.1 b/man/man1/gdal_merge.1
index d3514b3..8d1c005 100644
--- a/man/man1/gdal_merge.1
+++ b/man/man1/gdal_merge.1
@@ -1,4 +1,4 @@
-.TH "gdal_merge" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_merge" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_pansharpen.1 b/man/man1/gdal_pansharpen.1
index ccff2ff..38dfaa3 100644
--- a/man/man1/gdal_pansharpen.1
+++ b/man/man1/gdal_pansharpen.1
@@ -1,4 +1,4 @@
-.TH "gdal_pansharpen" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_pansharpen" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_polygonize.1 b/man/man1/gdal_polygonize.1
index 6dafb6a..7a6f243 100644
--- a/man/man1/gdal_polygonize.1
+++ b/man/man1/gdal_polygonize.1
@@ -1,4 +1,4 @@
-.TH "gdal_polygonize" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_polygonize" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_proximity.1 b/man/man1/gdal_proximity.1
index d51b458..9b361aa 100644
--- a/man/man1/gdal_proximity.1
+++ b/man/man1/gdal_proximity.1
@@ -1,4 +1,4 @@
-.TH "gdal_proximity" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_proximity" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_rasterize.1 b/man/man1/gdal_rasterize.1
index 78fcadf..0a35cab 100644
--- a/man/man1/gdal_rasterize.1
+++ b/man/man1/gdal_rasterize.1
@@ -1,4 +1,4 @@
-.TH "gdal_rasterize" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_rasterize" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_retile.1 b/man/man1/gdal_retile.1
index 0f7693b..3f7ff02 100644
--- a/man/man1/gdal_retile.1
+++ b/man/man1/gdal_retile.1
@@ -1,4 +1,4 @@
-.TH "gdal_retile" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_retile" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_sieve.1 b/man/man1/gdal_sieve.1
index 282ba51..5f150e1 100644
--- a/man/man1/gdal_sieve.1
+++ b/man/man1/gdal_sieve.1
@@ -1,4 +1,4 @@
-.TH "gdal_sieve" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_sieve" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_translate.1 b/man/man1/gdal_translate.1
index 64bd805..6cbd942 100644
--- a/man/man1/gdal_translate.1
+++ b/man/man1/gdal_translate.1
@@ -1,4 +1,4 @@
-.TH "gdal_translate" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_translate" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_utilities.1 b/man/man1/gdal_utilities.1
index f811689..7d038c1 100644
--- a/man/man1/gdal_utilities.1
+++ b/man/man1/gdal_utilities.1
@@ -1,4 +1,4 @@
-.TH "gdal_utilities" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_utilities" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaladdo.1 b/man/man1/gdaladdo.1
index 2196b26..761a8c6 100644
--- a/man/man1/gdaladdo.1
+++ b/man/man1/gdaladdo.1
@@ -1,4 +1,4 @@
-.TH "gdaladdo" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdaladdo" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalbuildvrt.1 b/man/man1/gdalbuildvrt.1
index 5614a5a..48f426c 100644
--- a/man/man1/gdalbuildvrt.1
+++ b/man/man1/gdalbuildvrt.1
@@ -1,4 +1,4 @@
-.TH "gdalbuildvrt" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalbuildvrt" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalcompare.1 b/man/man1/gdalcompare.1
index 188f058..9a5a839 100644
--- a/man/man1/gdalcompare.1
+++ b/man/man1/gdalcompare.1
@@ -1,4 +1,4 @@
-.TH "gdalcompare" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalcompare" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaldem.1 b/man/man1/gdaldem.1
index 35740b3..9c2c237 100644
--- a/man/man1/gdaldem.1
+++ b/man/man1/gdaldem.1
@@ -1,4 +1,4 @@
-.TH "gdaldem" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdaldem" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalinfo.1 b/man/man1/gdalinfo.1
index 5e2027d..792dcde 100644
--- a/man/man1/gdalinfo.1
+++ b/man/man1/gdalinfo.1
@@ -1,4 +1,4 @@
-.TH "gdalinfo" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalinfo" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdallocationinfo.1 b/man/man1/gdallocationinfo.1
index 4e6d7e1..e156578 100644
--- a/man/man1/gdallocationinfo.1
+++ b/man/man1/gdallocationinfo.1
@@ -1,4 +1,4 @@
-.TH "gdallocationinfo" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdallocationinfo" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalmanage.1 b/man/man1/gdalmanage.1
index 0a6d032..5639c40 100644
--- a/man/man1/gdalmanage.1
+++ b/man/man1/gdalmanage.1
@@ -1,4 +1,4 @@
-.TH "gdalmanage" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalmanage" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalmove.1 b/man/man1/gdalmove.1
index 2746e71..7c77b1f 100644
--- a/man/man1/gdalmove.1
+++ b/man/man1/gdalmove.1
@@ -1,4 +1,4 @@
-.TH "gdalmove" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalmove" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalsrsinfo.1 b/man/man1/gdalsrsinfo.1
index 98a128c..d83788d 100644
--- a/man/man1/gdalsrsinfo.1
+++ b/man/man1/gdalsrsinfo.1
@@ -1,4 +1,4 @@
-.TH "gdalsrsinfo" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalsrsinfo" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaltindex.1 b/man/man1/gdaltindex.1
index 6af3502..5c8670b 100644
--- a/man/man1/gdaltindex.1
+++ b/man/man1/gdaltindex.1
@@ -1,4 +1,4 @@
-.TH "gdaltindex" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdaltindex" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaltransform.1 b/man/man1/gdaltransform.1
index 2268636..49896ce 100644
--- a/man/man1/gdaltransform.1
+++ b/man/man1/gdaltransform.1
@@ -1,4 +1,4 @@
-.TH "gdaltransform" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdaltransform" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalwarp.1 b/man/man1/gdalwarp.1
index 053156f..3c39dfc 100644
--- a/man/man1/gdalwarp.1
+++ b/man/man1/gdalwarp.1
@@ -1,4 +1,4 @@
-.TH "gdalwarp" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalwarp" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gnm_utilities.1 b/man/man1/gnm_utilities.1
index 0d3c45e..75e364c 100644
--- a/man/man1/gnm_utilities.1
+++ b/man/man1/gnm_utilities.1
@@ -1,4 +1,4 @@
-.TH "gnm_utilities" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gnm_utilities" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gnmanalyse.1 b/man/man1/gnmanalyse.1
index f76035d..8a56d71 100644
--- a/man/man1/gnmanalyse.1
+++ b/man/man1/gnmanalyse.1
@@ -1,4 +1,4 @@
-.TH "gnmanalyse" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gnmanalyse" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gnmmanage.1 b/man/man1/gnmmanage.1
index a82e852..54a970e 100644
--- a/man/man1/gnmmanage.1
+++ b/man/man1/gnmmanage.1
@@ -1,4 +1,4 @@
-.TH "gnmmanage" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "gnmmanage" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/nearblack.1 b/man/man1/nearblack.1
index 15b4e3f..573041d 100644
--- a/man/man1/nearblack.1
+++ b/man/man1/nearblack.1
@@ -1,4 +1,4 @@
-.TH "nearblack" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "nearblack" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogr2ogr.1 b/man/man1/ogr2ogr.1
index e5bccb8..bfb4369 100644
--- a/man/man1/ogr2ogr.1
+++ b/man/man1/ogr2ogr.1
@@ -1,4 +1,4 @@
-.TH "ogr2ogr" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "ogr2ogr" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogr_utilities.1 b/man/man1/ogr_utilities.1
index 2d53389..236ee41 100644
--- a/man/man1/ogr_utilities.1
+++ b/man/man1/ogr_utilities.1
@@ -1,4 +1,4 @@
-.TH "ogr_utilities" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "ogr_utilities" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogrinfo.1 b/man/man1/ogrinfo.1
index 271b65a..0393af8 100644
--- a/man/man1/ogrinfo.1
+++ b/man/man1/ogrinfo.1
@@ -1,4 +1,4 @@
-.TH "ogrinfo" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "ogrinfo" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogrlineref.1 b/man/man1/ogrlineref.1
index bbd3260..8c6921e 100644
--- a/man/man1/ogrlineref.1
+++ b/man/man1/ogrlineref.1
@@ -1,4 +1,4 @@
-.TH "ogrlineref" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "ogrlineref" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogrtindex.1 b/man/man1/ogrtindex.1
index 452476a..4c97ac8 100644
--- a/man/man1/ogrtindex.1
+++ b/man/man1/ogrtindex.1
@@ -1,4 +1,4 @@
-.TH "ogrtindex" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "ogrtindex" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/pct2rgb.1 b/man/man1/pct2rgb.1
index cab9e86..77da77b 100644
--- a/man/man1/pct2rgb.1
+++ b/man/man1/pct2rgb.1
@@ -1,4 +1,4 @@
-.TH "pct2rgb" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "pct2rgb" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/rgb2pct.1 b/man/man1/rgb2pct.1
index 17c0531..610242d 100644
--- a/man/man1/rgb2pct.1
+++ b/man/man1/rgb2pct.1
@@ -1,4 +1,4 @@
-.TH "rgb2pct" 1 "Mon Oct 24 2016" "GDAL" \" -*- nroff -*-
+.TH "rgb2pct" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/nmake.opt b/nmake.opt
index 418c759..1a29cca 100644
--- a/nmake.opt
+++ b/nmake.opt
@@ -1,4 +1,4 @@
-# $Id: nmake.opt 33775 2016-03-23 20:25:05Z tamas $
+# $Id: nmake.opt 35970 2016-10-27 11:27:30Z jef $
 #
 # nmake.opt - main configuration file for NMAKE makefiles.
 #
@@ -237,7 +237,7 @@ BSB_SUPPORTED = 1
 # Comment out the following to disable ODBC support.
 ODBC_SUPPORTED = 1
 
-# Uncomment out the following to enable SQL Native Client support for MSSQL Bulk Copy.
+# Uncomment out the following to enable plugin with SQL Native Client support for MSSQL Bulk Copy.
 #SQLNCLI_VERSION = 11
 #SQLNCLI_DIR = C:\Program Files (x86)\Microsoft SQL Server\$(SQLNCLI_VERSION)0\SDK
 #SQLNCLI_LIB = "$(SQLNCLI_DIR)\Lib\x86\sqlncli$(SQLNCLI_VERSION).lib"
@@ -872,5 +872,4 @@ EXTERNAL_LIBS =	$(OGDILIB) $(XERCES_LIB) $(EXPAT_LIB) $(OCI_LIB) $(PG_LIB) \
 	$(ODBCLIB) $(JASPER_LIB) $(PNG_LIB) $(ADD_LIBS) $(OPENJPEG_LIB) \
 	$(MRSID_LIDAR_LIB) $(LIBKML_LIBS) $(SOSI_LIBS) $(PDF_LIB_LINK) $(LZMA_LIBS) \
 	$(LIBICONV_LIBRARY) $(WEBP_LIBS) $(FGDB_LIB_LINK) $(FREEXL_LIBS) $(GTA_LIBS) \
-	$(INGRES_LIB) $(LIBXML2_LIB) $(PCRE_LIB) $(MONGODB_LIB_LINK) $(CRYPTOPP_LIB) $(SQLNCLI_LIB) ws2_32.lib
-		
+	$(INGRES_LIB) $(LIBXML2_LIB) $(PCRE_LIB) $(MONGODB_LIB_LINK) $(CRYPTOPP_LIB) ws2_32.lib
diff --git a/ogr/gml2ogrgeometry.cpp b/ogr/gml2ogrgeometry.cpp
index 11b0f06..f06ba00 100644
--- a/ogr/gml2ogrgeometry.cpp
+++ b/ogr/gml2ogrgeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gml2ogrgeometry.cpp 33631 2016-03-04 06:28:09Z goatbar $
+ * $Id: gml2ogrgeometry.cpp 37130 2017-01-12 21:15:22Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Code to translate between GML and OGR geometry forms.
@@ -1122,7 +1122,8 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     if( poCC == NULL )
                     {
                         poCC = new OGRCompoundCurve();
-                        if( poCC->addCurveDirectly(poRing) != OGRERR_NONE )
+                        bool bIgnored = false;
+                        if( !GML2OGRGeometry_AddToCompositeCurve(poCC, poRing, bIgnored) )
                         {
                             delete poGeom;
                             delete poRing;
@@ -1184,7 +1185,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                         }
                     }
 
-                    if( poCC->addCurveDirectly((OGRCurve*)poGeom) != OGRERR_NONE )
+                    bool bIgnored = false;
+                    if( !GML2OGRGeometry_AddToCompositeCurve( poCC,
+                                                              poGeom,
+                                                              bIgnored ) )
                     {
                         delete poGeom;
                         delete poCC;
diff --git a/ogr/ogrct.cpp b/ogr/ogrct.cpp
index aa5e1c9..47d93bc 100644
--- a/ogr/ogrct.cpp
+++ b/ogr/ogrct.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrct.cpp 33631 2016-03-04 06:28:09Z goatbar $
+ * $Id: ogrct.cpp 37167 2017-01-17 16:38:55Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSCoordinateTransformation class.
@@ -39,7 +39,7 @@
 #include "proj_api.h"
 #endif
 
-CPL_CVSID("$Id: ogrct.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogrct.cpp 37167 2017-01-17 16:38:55Z rouault $");
 
 /* ==================================================================== */
 /*      PROJ.4 interface stuff.                                         */
@@ -157,6 +157,8 @@ class OGRProj4CT : public OGRCoordinateTransformation
     double     *padfTargetY;
     double     *padfTargetZ;
 
+    bool        bNoTransform;
+
 public:
                 OGRProj4CT();
     virtual     ~OGRProj4CT();
@@ -855,20 +857,16 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
         return FALSE;
     }
 
-    /* Determine if we really have a transformation to do */
-    bIdentityTransform = (strcmp(pszSrcProj4Defn, pszDstProj4Defn) == 0);
+    // Determine if we really have a transformation to do at the proj.4 level
+    // (but we may have a unit transformation to do)
+    bIdentityTransform = strcmp(pszSrcProj4Defn, pszDstProj4Defn) == 0;
 
-#if 0
-    /* In case of identity transform, under the following conditions, */
-    /* we can also avoid transforming from degrees <--> radians. */
-    if( bIdentityTransform && bSourceLatLong && !bSourceWrap &&
-        bTargetLatLong && !bTargetWrap &&
-        fabs(dfSourceToRadians * dfTargetFromRadians - 1.0) < 1e-10 )
-    {
-        /*bSourceLatLong = FALSE;
-        bTargetLatLong = FALSE;*/
-    }
-#endif
+    // Determine if we can skip the tranformation completely.
+    // Assume that source and target units are defined with at least
+    // 10 correct significant digits; hence the 1E-9 tolerance used.
+    bNoTransform = bIdentityTransform && bSourceLatLong && !bSourceWrap &&
+                   bTargetLatLong && !bTargetWrap &&
+                   fabs(dfSourceToRadians * dfTargetFromRadians - 1.0) < 1E-9;
 
     CPLFree( pszSrcProj4Defn );
     CPLFree( pszDstProj4Defn );
@@ -946,6 +944,20 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
                              int *pabSuccess )
 
 {
+    // Prevent any coordinate modification when possible
+    if ( bNoTransform )
+    {
+        if( pabSuccess )
+        {
+            for( int i = 0; i < nCount; i++ )
+            {
+                 pabSuccess[i] = TRUE;
+            }
+        }
+        return TRUE;
+    }
+
+
     int   err, i;
 
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrgeometryfactory.cpp b/ogr/ogrgeometryfactory.cpp
index e6a62ed..1097319 100644
--- a/ogr/ogrgeometryfactory.cpp
+++ b/ogr/ogrgeometryfactory.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeometryfactory.cpp 34396 2016-06-23 17:12:10Z rouault $
+ * $Id: ogrgeometryfactory.cpp 37132 2017-01-12 21:29:13Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Factory for converting geometry to and from well known binary
@@ -41,7 +41,7 @@
 #define UNUSED_IF_NO_GEOS
 #endif
 
-CPL_CVSID("$Id: ogrgeometryfactory.cpp 34396 2016-06-23 17:12:10Z rouault $");
+CPL_CVSID("$Id: ogrgeometryfactory.cpp 37132 2017-01-12 21:29:13Z rouault $");
 
 /************************************************************************/
 /*                           createFromWkb()                            */
@@ -3602,7 +3602,7 @@ OGRLineString* OGRGeometryFactory::curveToLineString(
                                     alpha0, alpha2, dfStep,
                                     bStealth);
 
-        if( bStealth )
+        if( bStealth && poLine->getNumPoints() > 6 )
         {
             /* 'Hide' the angle of the intermediate point in the 8 low-significant */
             /* bits of the x,y of the first 2 computed points (so 32 bits), */
diff --git a/ogr/ogrsf_frmts/amigocloud/ogramigoclouddatasource.cpp b/ogr/ogrsf_frmts/amigocloud/ogramigoclouddatasource.cpp
index 898faec..e7293f4 100644
--- a/ogr/ogrsf_frmts/amigocloud/ogramigoclouddatasource.cpp
+++ b/ogr/ogrsf_frmts/amigocloud/ogramigoclouddatasource.cpp
@@ -162,6 +162,11 @@ int OGRAmigoCloudDataSource::Open( const char * pszFilename,
     osAPIKey = CSLFetchNameValueDef(papszOpenOptionsIn, "API_KEY",
                                     CPLGetConfigOption("AMIGOCLOUD_API_KEY", ""));
 
+    if (osAPIKey.empty())
+    {
+        osAPIKey = OGRAMIGOCLOUDGetOptionValue(pszFilename, "API_KEY");
+    }
+
     CPLString osDatasets = OGRAMIGOCLOUDGetOptionValue(pszFilename, "datasets");
 
     bUseHTTPS = CPLTestBool(CPLGetConfigOption("AMIGOCLOUD_HTTPS", "YES"));
diff --git a/ogr/ogrsf_frmts/amigocloud/ogramigocloudlayer.cpp b/ogr/ogrsf_frmts/amigocloud/ogramigocloudlayer.cpp
index a928a10..b025d81 100644
--- a/ogr/ogrsf_frmts/amigocloud/ogramigocloudlayer.cpp
+++ b/ogr/ogrsf_frmts/amigocloud/ogramigocloudlayer.cpp
@@ -172,8 +172,8 @@ OGRFeature *OGRAmigoCloudLayer::BuildFeature(json_object* poRowObj)
 json_object* OGRAmigoCloudLayer::FetchNewFeatures(GIntBig iNextIn)
 {
     CPLString osSQL = osBaseSQL;
-    if( osSQL.ifind("SELECT") != std::string::npos &&
-        osSQL.ifind(" LIMIT ") == std::string::npos )
+    if (osSQL.ifind("SELECT") != std::string::npos &&
+        osSQL.ifind(" LIMIT ") == std::string::npos)
     {
         osSQL += " LIMIT ";
         osSQL += CPLSPrintf("%d", GetFeaturesToFetch());
@@ -244,9 +244,8 @@ OGRFeature *OGRAmigoCloudLayer::GetNextRawFeature()
     OGRFeature* poFeature = BuildFeature(poRowObj);
 
     std::map<GIntBig, OGRAmigoCloudFID>::iterator it = mFIDs.find(poFeature->GetFID());
-    if(it!=mFIDs.end())
+    if (it != mFIDs.end())
     {
-//        iNext = poFeature->GetFID() + 1;
         iNext = it->second.iIndex + 1;
     }
 
diff --git a/ogr/ogrsf_frmts/amigocloud/ogramigocloudtablelayer.cpp b/ogr/ogrsf_frmts/amigocloud/ogramigocloudtablelayer.cpp
index af01280..f2a7888 100644
--- a/ogr/ogrsf_frmts/amigocloud/ogramigocloudtablelayer.cpp
+++ b/ogr/ogrsf_frmts/amigocloud/ogramigocloudtablelayer.cpp
@@ -233,6 +233,15 @@ json_object* OGRAmigoCloudTableLayer::FetchNewFeatures(GIntBig iNextIn)
         {
             osSQL.Printf("%s", osSELECTWithoutWHERE.c_str());
         }
+
+        if (osSQL.ifind("SELECT") != std::string::npos &&
+            osSQL.ifind(" LIMIT ") == std::string::npos)
+        {
+            osSQL += " LIMIT ";
+            osSQL += CPLSPrintf("%d", GetFeaturesToFetch());
+            osSQL += " OFFSET ";
+            osSQL += CPLSPrintf(CPL_FRMT_GIB, iNextIn);
+        }
         return poDS->RunSQL(osSQL);
     }
     else
diff --git a/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp b/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
index 4aa7ab7..69cf8f2 100644
--- a/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogresrijsonreader.cpp 34298 2016-05-26 17:14:18Z rouault $
+ * $Id: ogresrijsonreader.cpp 37099 2017-01-11 12:21:34Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRESRIJSONReader class (OGR ESRIJSON Driver)
@@ -691,7 +691,7 @@ static int OGRESRIJSONReaderParseXYZMArray (json_object* poObjCoords,
 /*                        OGRESRIJSONReadLineString()                   */
 /************************************************************************/
 
-OGRLineString* OGRESRIJSONReadLineString( json_object* poObj)
+OGRGeometry* OGRESRIJSONReadLineString( json_object* poObj)
 {
     CPLAssert( NULL != poObj );
 
@@ -721,8 +721,8 @@ OGRLineString* OGRESRIJSONReadLineString( json_object* poObj)
         return NULL;
     }
 
-    OGRLineString* poLine
-        = new OGRLineString();
+    OGRMultiLineString* poMLS = NULL;
+    OGRGeometry* poRet = NULL;
     const int nPaths = json_object_array_length( poObjPaths );
     for(int iPath = 0; iPath < nPaths; iPath ++)
     {
@@ -730,12 +730,24 @@ OGRLineString* OGRESRIJSONReadLineString( json_object* poObj)
         if ( poObjPath == NULL ||
                 json_type_array != json_object_get_type( poObjPath ) )
         {
-            delete poLine;
+            delete poRet;
             CPLDebug( "ESRIJSON",
                     "LineString: got non-array object." );
             return NULL;
         }
 
+        OGRLineString* poLine = new OGRLineString();
+        if( nPaths > 1 )
+        {
+            if( iPath == 0 )
+            {
+                poMLS = new OGRMultiLineString();
+                poRet = poMLS;
+            }
+            poMLS->addGeometryDirectly(poLine);
+        }
+        else
+            poRet = poLine;
         const int nPoints = json_object_array_length( poObjPath );
         for(int i = 0; i < nPoints; i++)
         {
@@ -747,6 +759,7 @@ OGRLineString* OGRESRIJSONReadLineString( json_object* poObj)
                     poObjCoords, &dfX, &dfY, &dfZ, &nNumCoords) )
             {
                 delete poLine;
+                delete poRet;
                 return NULL;
             }
 
@@ -760,8 +773,10 @@ OGRLineString* OGRESRIJSONReadLineString( json_object* poObj)
             }
         }
     }
+    if( poRet == NULL )
+        poRet = new OGRLineString();
 
-    return poLine;
+    return poRet;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
index e464afa..f831d59 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonreader.h 34331 2016-06-09 20:03:05Z rouault $
+ * $Id: ogrgeojsonreader.h 37099 2017-01-11 12:21:34Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines GeoJSON reader within OGR OGRGeoJSON Driver.
@@ -234,7 +234,7 @@ private:
 OGRSpatialReference* OGRESRIJSONReadSpatialReference( json_object* poObj );
 OGRwkbGeometryType OGRESRIJSONGetGeometryType( json_object* poObj );
 OGRPoint* OGRESRIJSONReadPoint( json_object* poObj);
-OGRLineString* OGRESRIJSONReadLineString( json_object* poObj);
+OGRGeometry* OGRESRIJSONReadLineString( json_object* poObj);
 OGRGeometry* OGRESRIJSONReadPolygon( json_object* poObj);
 OGRMultiPoint* OGRESRIJSONReadMultiPoint( json_object* poObj);
 
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp
index ba47ac2..9c55f40 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonwritelayer.cpp 32981 2016-01-14 15:06:42Z goatbar $
+ * $Id: ogrgeojsonwritelayer.cpp 35926 2016-10-25 14:37:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONWriteLayer class (OGR GeoJSON Driver).
@@ -132,7 +132,7 @@ OGRErr OGRGeoJSONWriteLayer::ICreateFeature( OGRFeature* poFeature )
     ++nOutCounter_;
 
     OGRGeometry* poGeometry = poFeature->GetGeometryRef();
-    if ( (bWriteBBOX || bWriteFC_BBOX) && !poGeometry->IsEmpty() )
+    if ( (bWriteBBOX || bWriteFC_BBOX) && poGeometry != NULL && !poGeometry->IsEmpty() )
     {
         OGREnvelope3D sEnvelope;
         poGeometry->getEnvelope(&sEnvelope);
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
index c68f572..00dcf25 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
@@ -655,9 +655,11 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
 
         if( CPLTestBool(CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "LIST_ALL_TABLES", "YES")) )
         {
+            // vgpkg_ is Spatialite virtual table
             osSQL += "UNION ALL "
                     "SELECT name, name, 0 as is_spatial, 0 AS xmin, 0 AS ymin, 0 AS xmax, 0 AS ymax, 0 AS is_gpkg_table "
                     "FROM sqlite_master WHERE type IN ('table', 'view') AND name NOT LIKE 'gpkg_%' "
+                    "AND name NOT LIKE 'vgpkg_%' "
                     "AND name NOT LIKE 'rtree_%' AND name NOT LIKE 'sqlite_%' "
                     "AND name NOT IN (SELECT table_name FROM gpkg_contents)";
         }
diff --git a/ogr/ogrsf_frmts/ili/ogr_ili1.h b/ogr/ogrsf_frmts/ili/ogr_ili1.h
index b0b4b7c..940b770 100644
--- a/ogr/ogrsf_frmts/ili/ogr_ili1.h
+++ b/ogr/ogrsf_frmts/ili/ogr_ili1.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_ili1.h 33325 2016-02-02 14:30:48Z rouault $
+ * $Id: ogr_ili1.h 36502 2016-11-25 14:21:53Z rouault $
  *
  * Project:  Interlis 1 Translator
  * Purpose:   Definition of classes for OGR Interlis 1 driver.
@@ -70,7 +70,7 @@ private:
     void                ResetReading();
     OGRFeature *        GetNextFeature();
     OGRFeature *        GetNextFeatureRef();
-    OGRFeature *        GetFeatureRef( long nFid );
+    OGRFeature *        GetFeatureRef( GIntBig nFid );
     OGRFeature *        GetFeatureRef( const char* );
 
     GIntBig             GetFeatureCount( int bForce = TRUE );
diff --git a/ogr/ogrsf_frmts/ili/ogrili1layer.cpp b/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
index 23a19ac..13c79f6 100644
--- a/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrili1layer.cpp 35780 2016-10-17 10:07:12Z rouault $
+ * $Id: ogrili1layer.cpp 36502 2016-11-25 14:21:53Z rouault $
  *
  * Project:  Interlis 1 Translator
  * Purpose:  Implements OGRILI1Layer class.
@@ -33,7 +33,10 @@
 #include "ogr_geos.h"
 #include "ogr_ili1.h"
 
-CPL_CVSID("$Id: ogrili1layer.cpp 35780 2016-10-17 10:07:12Z rouault $");
+#include <map>
+#include <vector>
+
+CPL_CVSID("$Id: ogrili1layer.cpp 36502 2016-11-25 14:21:53Z rouault $");
 
 /************************************************************************/
 /*                           OGRILI1Layer()                              */
@@ -130,7 +133,7 @@ OGRFeature *OGRILI1Layer::GetNextFeatureRef() {
 /*                             GetFeatureRef()                          */
 /************************************************************************/
 
-OGRFeature *OGRILI1Layer::GetFeatureRef( long nFID )
+OGRFeature *OGRILI1Layer::GetFeatureRef( GIntBig nFID )
 
 {
     OGRFeature *poFeature;
@@ -500,8 +503,12 @@ void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfaceLineLayer,
               GetLayerDefn()->GetName());
     OGRwkbGeometryType geomType
         = GetLayerDefn()->GetGeomFieldDefn(nSurfaceFieldIndex)->GetType();
-    OGRCompoundCurve *surface_lines = NULL; // collected lines of SURFACE polygon ring
+
+    std::map<OGRFeature*, std::vector<OGRCurve*> > oMapFeatureToGeomSet;
+
     poSurfaceLineLayer->ResetReading();
+
+    // First map: for each target curvepolygon, find all belonging curves
     while (OGRFeature *linefeature = poSurfaceLineLayer->GetNextFeatureRef()) {
         //OBJE entries with same _RefTID are polygon rings of same feature
         OGRFeature *feature;
@@ -512,66 +519,211 @@ void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfaceLineLayer,
         else
         {
           GIntBig reftid = linefeature->GetFieldAsInteger64(1);
-          feature = GetFeatureRef((int)reftid);
+          feature = GetFeatureRef(reftid);
         }
-        if (feature) {
-            if (!feature->GetGeomFieldRef(nSurfaceFieldIndex)) {
-                OGRCurvePolygon *newpoly = (geomType == wkbPolygon) ?
-                    new OGRPolygon() : new OGRCurvePolygon();
-                feature->SetGeomFieldDirectly(nSurfaceFieldIndex, newpoly);
+        if (feature)
+        {
+            OGRGeometry* poGeom = linefeature->GetGeomFieldRef(0);
+            OGRMultiCurve *curves = dynamic_cast<OGRMultiCurve *>(poGeom);
+            if( curves )
+            {
+                for (int i=0; i<curves->getNumGeometries(); i++)
+                {
+                    OGRCurve* curve = reinterpret_cast<OGRCurve*>(
+                                                    curves->getGeometryRef(i));
+                    if( !curve->IsEmpty() )
+                        oMapFeatureToGeomSet[feature].push_back(curve);
+                }
             }
-            OGRCurvePolygon *poly = reinterpret_cast<OGRCurvePolygon *>(
-                        feature->GetGeomFieldRef(nSurfaceFieldIndex) );
-            OGRMultiCurve *lines = reinterpret_cast<OGRMultiCurve *>(
-                linefeature->GetGeomFieldRef(0) );
-            for( int i = 0; lines != NULL && i < lines->getNumGeometries(); i++ ) {
-                OGRCurve *line = reinterpret_cast<OGRCurve*>(lines->getGeometryRef(i));
-                OGRCurve *ring = NULL;
-                if (surface_lines) {
-                    //SURFACE polygon lines spread over multiple OBJECTs, so we collect curves
-                    if (line->getGeometryType() == wkbCompoundCurve) {
-                        OGRCompoundCurve* ccurve = reinterpret_cast<OGRCompoundCurve *>(line);
-                        for (int j=0; j<ccurve->getNumCurves(); j++) {
-                            surface_lines->addCurve(ccurve->getCurve(j));
+        }
+        else
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Couldn't join feature FID " CPL_FRMT_GIB,
+                      linefeature->GetFieldAsInteger64(1) );
+        }
+    }
+
+    // Now for each target polygon, assemble the curves together.
+    std::map<OGRFeature*, std::vector<OGRCurve*> >::const_iterator oIter =
+                                                oMapFeatureToGeomSet.begin();
+    for( ; oIter != oMapFeatureToGeomSet.end(); ++oIter )
+    {
+        OGRFeature* feature = oIter->first;
+        std::vector<OGRCurve*> oCurves = oIter->second;
+
+        std::vector<OGRCurve*> oSetDestCurves;
+        double dfLargestArea = 0.0;
+        OGRCurve* poLargestCurve = NULL;
+        while( true )
+        {
+            std::vector<OGRCurve*>::iterator oIterCurves = oCurves.begin();
+            if( oIterCurves == oCurves.end() )
+                break;
+
+            OGRPoint endPointCC;
+            OGRCompoundCurve* poCC = new OGRCompoundCurve();
+ 
+            bool bFirst = true;
+            while( true )
+            {
+                bool bNewCurveAdded = false;
+                const double dfEps = 1e-14;
+                for(oIterCurves = oCurves.begin();
+                                oIterCurves != oCurves.end(); ++oIterCurves )
+                {
+                    OGRCurve* curve = *oIterCurves;
+                    OGRPoint startPoint;
+                    OGRPoint endPoint;
+                    curve->StartPoint(&startPoint);
+                    curve->EndPoint(&endPoint);
+                    if( bFirst ||
+                        (fabs(startPoint.getX() - endPointCC.getX()) < dfEps &&
+                         fabs(startPoint.getY() - endPointCC.getY()) < dfEps) )
+                    {
+                        bFirst = false;
+
+                        curve->EndPoint(&endPointCC);
+
+                        const OGRwkbGeometryType eCurveType =
+                                        wkbFlatten(curve->getGeometryType());
+                        if( eCurveType == wkbCompoundCurve )
+                        {
+                            OGRCompoundCurve* poCCSub =
+                                    reinterpret_cast<OGRCompoundCurve*>(curve);
+                            for( int i=0; i < poCCSub->getNumCurves(); ++i )
+                            {
+                                poCC->addCurve(poCCSub->getCurve(i));
+                            }
                         }
-                    } else { // wkbLineString (linearized)
-                        surface_lines->addCurve(line);
-                    }
-                    line = surface_lines;
-                }
-                if (line->get_IsClosed()) {
-                    if (geomType == wkbPolygon) {
-                        ring = OGRCurve::CastToLinearRing(reinterpret_cast<OGRCurve*>(
-                                 line->clone()));
-                    } else { // wkbMultiCurve
-                        ring = reinterpret_cast<OGRCurve*>(line->clone());
+                        else
+                        {
+                            poCC->addCurve( curve );
+                        }
+                        oCurves.erase( oIterCurves );
+                        bNewCurveAdded = true;
+                        break;
                     }
-                    if( line == surface_lines ) {
-                        delete surface_lines;
-                        surface_lines = NULL;
-                        line = NULL; /* to make CLang Static Analyzer happy */
+                    else
+                    if( fabs(endPoint.getX() - endPointCC.getX()) < dfEps &&
+                        fabs(endPoint.getY() - endPointCC.getY()) < dfEps )
+                    {
+                        curve->StartPoint(&endPointCC);
+
+                        const OGRwkbGeometryType eCurveType =
+                                        wkbFlatten(curve->getGeometryType());
+                        if( eCurveType == wkbLineString ||
+                            eCurveType == wkbCircularString )
+                        {
+                            OGRSimpleCurve* poSC =
+                              reinterpret_cast<OGRSimpleCurve*>(
+                                  (reinterpret_cast<OGRSimpleCurve*>(curve))
+                                                                    ->clone());
+                            poSC->reversePoints();
+                            poCC->addCurveDirectly( poSC );
+                        }
+                        else if( eCurveType == wkbCompoundCurve )
+                        {
+                            // Reverse the order of the elements of the
+                            // compound curve
+                            OGRCompoundCurve* poCCSub =
+                                    reinterpret_cast<OGRCompoundCurve*>(curve);
+                            for( int i=poCCSub->getNumCurves()-1; i >= 0; --i )
+                            {
+                                OGRSimpleCurve* poSC =
+                                    reinterpret_cast<OGRSimpleCurve*>(
+                                        (reinterpret_cast<OGRSimpleCurve*>(
+                                            poCCSub->getCurve(i)))->clone());
+                                poSC->reversePoints();
+                                poCC->addCurveDirectly(poSC);
+                            }
+                        }
+
+                        oCurves.erase( oIterCurves );
+                        bNewCurveAdded = true;
+                        break;
                     }
                 }
-                if (ring == NULL && surface_lines == NULL && line != NULL) {
-                    //SURFACE polygon lines spread over multiple OBJECTs, so we collect curves
-                    if (line->getGeometryType() == wkbCompoundCurve) {
-                        surface_lines = reinterpret_cast<OGRCompoundCurve *>(line->clone());
-                    } else { // wkbLineString (linearized)
-                        surface_lines = new OGRCompoundCurve();
-                        surface_lines->addCurve(line);
-                    }
+                if( !bNewCurveAdded || oCurves.empty() || poCC->get_IsClosed() )
+                    break;
+            }
+
+            if( !poCC->get_IsClosed() )
+            {
+                char* pszJSon = poCC->exportToJson();
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "A ring %s for feature " CPL_FRMT_GIB " in layer %s "
+                         "was not closed. Dropping it",
+                         pszJSon, feature->GetFID(), GetName());
+                delete poCC;
+                CPLFree(pszJSon);
+            }
+            else
+            {
+                double dfArea = poCC->get_Area();
+                if( dfArea >= dfLargestArea )
+                {
+                    dfLargestArea = dfArea;
+                    poLargestCurve = poCC;
                 }
-                if (ring) {
-                    OGRErr error = poly->addRingDirectly(ring);
-                    if (error != OGRERR_NONE) {
-                        CPLError(CE_Warning, CPLE_AppDefined, "Added geometry: %s", ring->exportToJson() );
-                    }
+                oSetDestCurves.push_back(poCC);
+            }
+        }
+
+        // Now build the final polygon by first inserting the largest ring.
+        OGRCurvePolygon *poPoly = (geomType == wkbPolygon) ?
+                                new OGRPolygon() : new OGRCurvePolygon();
+        if( poLargestCurve )
+        {
+            std::vector<OGRCurve*>::iterator oIterCurves =
+                                                    oSetDestCurves.begin();
+            for( ; oIterCurves != oSetDestCurves.end(); ++oIterCurves )
+            {
+                OGRCurve* poCurve = *oIterCurves;
+                if( poCurve == poLargestCurve )
+                {
+                    oSetDestCurves.erase( oIterCurves );
+                    break;
+                }
+            }
+
+            if (geomType == wkbPolygon)
+            {
+                poLargestCurve = OGRCurve::CastToLinearRing(poLargestCurve);
+            }
+            OGRErr error = poPoly->addRingDirectly(poLargestCurve);
+            if (error != OGRERR_NONE)
+            {
+                char* pszJSon = poLargestCurve->exportToJson();
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Cannot add ring %s to feature " CPL_FRMT_GIB
+                         " in layer %s",
+                         pszJSon, feature->GetFID(), GetName() );
+                CPLFree(pszJSon);
+            }
+
+            oIterCurves = oSetDestCurves.begin();
+            for( ; oIterCurves != oSetDestCurves.end(); ++oIterCurves )
+            {
+                OGRCurve* poCurve = *oIterCurves;
+                if (geomType == wkbPolygon)
+                {
+                    poCurve = OGRCurve::CastToLinearRing(poCurve);
+                }
+                error = poPoly->addRingDirectly(poCurve);
+                if (error != OGRERR_NONE)
+                {
+                    char* pszJSon = poCurve->exportToJson();
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "Cannot add ring %s to feature " CPL_FRMT_GIB
+                            " in layer %s",
+                            pszJSon, feature->GetFID(), GetName() );
+                    CPLFree(pszJSon);
                 }
             }
-        } else {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Couldn't join feature FID " CPL_FRMT_GIB, linefeature->GetFieldAsInteger64(1) );
         }
+
+        feature->SetGeomFieldDirectly(nSurfaceFieldIndex, poPoly);
     }
 
     ResetReading();
diff --git a/ogr/ogrsf_frmts/makefile.vc b/ogr/ogrsf_frmts/makefile.vc
index 208c973..9c1b954 100644
--- a/ogr/ogrsf_frmts/makefile.vc
+++ b/ogr/ogrsf_frmts/makefile.vc
@@ -28,7 +28,8 @@ PLUGINDIRLIST	=	$(PLUGIN_ARCOBJECTS_DIR) \
 			$(PLUGIN_SDE_DIR) \
 			$(PLUGIN_INGRESDIR) \
 			$(PLUGIN_LIBKMLDIR) \
-            $(PLUGIN_MONGODBDIR)
+			$(PLUGIN_MONGODBDIR) \
+			$(PLUGIN_MSSPATIALDIR)
 
 !IFDEF OGDIDIR
 OGDIDIR	=	ogdi
@@ -40,9 +41,13 @@ ODBCDIR	=	odbc pgeo mssqlspatial geomedia db2 walk
 ODBCOBJ =	odbc\*.obj pgeo\*.obj mssqlspatial\*.obj geomedia\*.obj db2\*.obj walk\*.obj
 !ENDIF
 
+!IFDEF SQLNCLI_LIB
+PLUGIN_MSSPATIALDIR = mssqlspatial
+!ENDIF
+
 !IFDEF SQLITE_LIB
-SQLITE_DIR	=	sqlite gpkg
-SQLITE_OBJ =	sqlite\*.obj gpkg\*.obj
+SQLITE_DIR	= sqlite gpkg
+SQLITE_OBJ	= sqlite\*.obj gpkg\*.obj
 !ENDIF
 
 !IFDEF OCI_LIB
@@ -57,7 +62,7 @@ PLUGIN_OCIDIR = oci
 !IFDEF INGRES_HOME
 !IF "$(INGRES_PLUGIN)" != "YES"
 INGRESDIR	=	ingres
-INGRESOBJ =	ingres\*.obj
+INGRESOBJ	=	ingres\*.obj
 !ELSE
 PLUGIN_INGRESDIR =	ingres
 !ENDIF
@@ -289,7 +294,7 @@ plugindirs:
 clean:
 	-del ogrsf_frmts.lib
 	-del ogrsf_frmts_sup.lib
-	for %d in ( $(DIRLIST) ) do \
+	for %d in ( $(DIRLIST) $(PLUGINDIRLIST) ) do \
 		cd %d \
 		&& $(MAKE) /f makefile.vc clean \
 		&& cd .. \
diff --git a/ogr/ogrsf_frmts/mssqlspatial/makefile.vc b/ogr/ogrsf_frmts/mssqlspatial/makefile.vc
index aaf44f1..98bf1b1 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/makefile.vc
+++ b/ogr/ogrsf_frmts/mssqlspatial/makefile.vc
@@ -1,28 +1,42 @@
+OBJ = \
+	.\ogrmssqlgeometryparser.obj \
+	.\ogrmssqlgeometryvalidator.obj \
+	.\ogrmssqlgeometrywriter.obj \
+	.\ogrmssqlspatialdatasource.obj \
+	.\ogrmssqlspatialdriver.obj \
+	.\ogrmssqlspatiallayer.obj \
+	.\ogrmssqlspatialselectlayer.obj \
+	.\ogrmssqlspatialtablelayer.obj
 
-OBJ	=	ogrmssqlspatialdriver.obj ogrmssqlspatialdatasource.obj ogrmssqlspatiallayer.obj ogrmssqlspatialtablelayer.obj ogrmssqlspatialselectlayer.obj ogrmssqlgeometryparser.obj ogrmssqlgeometryvalidator.obj ogrmssqlgeometrywriter.obj
+PLUGINOBJ = $(OBJ:.\=plugin\)
 
-PLUGIN_DLL = ogr_MSSQLSpatial.dll
+PLUGIN_DLL	= ogr_MSSQLSpatial.dll
 
-GDAL_ROOT	=	..\..\..
+GDAL_ROOT	= ..\..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-EXTRAFLAGS = -I.. -I..\.. $(SQLNCLI_INCLUDE)
+EXTRAFLAGS	= -I.. -I..\.. $(SQLNCLI_INCLUDE)
 
-default:	$(OBJ)
+default: $(OBJ)
+
+{.}.cpp{plugin\}.obj:
+	-mkdir plugin
+	$(CPP) $(CPPFLAGS) /DMSSQL_BCP_SUPPORTED=1 /Fo$@ /c $<
 
 plugin: $(PLUGIN_DLL)
 
-$(PLUGIN_DLL):	$(OBJ)
-	link /dll /out:$(PLUGIN_DLL) $(OBJ) $(GDALLIB) $(ODBCLIB) $(SQLNCLI_LIB) $(LDEBUG)
+$(PLUGIN_DLL):	$(PLUGINOBJ)
+	link /dll /out:$(PLUGIN_DLL) $(PLUGINOBJ) $(GDALLIB) $(ODBCLIB) $(SQLNCLI_LIB) $(LDEBUG)
 	if exist $(PLUGIN_DLL).manifest mt -manifest $(PLUGIN_DLL).manifest -outputresource:$(PLUGIN_DLL);2
 
 clean:
-    -del *.lib
+	-del *.lib
 	-del *.obj *.pdb *.exp
-    -del *.exe
+	-del *.exe
 	-del *.dll
 	-del *.manifest
+	-del plugin\*.obj
 
 plugin-install:
 	-mkdir $(PLUGINDIR)
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdriver.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdriver.cpp
index 572f2bf..2682d1e 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdriver.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatialdriver.cpp 32293 2015-12-20 01:21:31Z rouault $
+ * $Id: ogrmssqlspatialdriver.cpp 35970 2016-10-27 11:27:30Z jef $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
@@ -30,7 +30,7 @@
 #include "ogr_mssqlspatial.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrmssqlspatialdriver.cpp 32293 2015-12-20 01:21:31Z rouault $");
+CPL_CVSID("$Id: ogrmssqlspatialdriver.cpp 35970 2016-10-27 11:27:30Z jef $");
 
 /************************************************************************/
 /*                           ~OGRMSSQLSpatialDriver()                   */
@@ -124,7 +124,11 @@ void RegisterOGRMSSQLSpatial()
     OGRSFDriver* poDriver = new OGRMSSQLSpatialDriver;
 
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                               "Microsoft SQL Server Spatial Database" );
+                               "Microsoft SQL Server Spatial Database"
+#ifdef MSSQL_BCP_SUPPORTED
+			       " (BCP)"
+#endif
+	);
     poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_mssqlspatial.html" );
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
                                "<CreationOptionList/>");
diff --git a/ogr/ogrsf_frmts/nas/nasreader.cpp b/ogr/ogrsf_frmts/nas/nasreader.cpp
index c31e94a..1c442a9 100644
--- a/ogr/ogrsf_frmts/nas/nasreader.cpp
+++ b/ogr/ogrsf_frmts/nas/nasreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nasreader.cpp 33095 2016-01-22 17:55:56Z rouault $
+ * $Id: nasreader.cpp 36296 2016-11-19 15:02:05Z jef $
  *
  * Project:  NAS Reader
  * Purpose:  Implementation of NASReader class.
@@ -602,6 +602,7 @@ void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
                       poClass->GetName(), pszElement,
                       poProp->papszSubProperties[0], pszValue,
                       poIdProp && poIdProp->nSubProperties>0 &&
+                      poIdProp->papszSubProperties &&
                       poIdProp->papszSubProperties[0] ?
                       poIdProp->papszSubProperties[0] : "(null)" );
         }
diff --git a/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp b/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp
index 72904de..f888cf3 100644
--- a/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp
+++ b/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsdedatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogrsdedatasource.cpp 36090 2016-11-03 14:22:30Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSDEDataSource class.
@@ -34,7 +34,7 @@
 #include "cpl_string.h"
 #include "gdal.h"
 
-CPL_CVSID("$Id: ogrsdedatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrsdedatasource.cpp 36090 2016-11-03 14:22:30Z rouault $");
 
 /************************************************************************/
 /*                          OGRSDEDataSource()                           */
@@ -1324,7 +1324,7 @@ void OGRSDEDataSource::EnumerateSpatialTables()
 
     for( iTable = 0; iTable < nTableListCount; iTable++ )
     {
-       ICreateLayerFromRegInfo( ahTableList[iTable] );
+       CreateLayerFromRegInfo( ahTableList[iTable] );
     }
 
     SE_registration_free_info_list( nTableListCount, ahTableList );
@@ -1354,14 +1354,14 @@ void OGRSDEDataSource::OpenSpatialTable( const char* pszTableName )
     }
     else
     {
-       ICreateLayerFromRegInfo( tableinfo );
+       CreateLayerFromRegInfo( tableinfo );
     }
 
     SE_reginfo_free( tableinfo );
 }
 
 /************************************************************************/
-/*                      ICreateLayerFromRegInfo()                       */
+/*                      CreateLayerFromRegInfo()                       */
 /************************************************************************/
 
 void OGRSDEDataSource::CreateLayerFromRegInfo( SE_REGINFO& reginfo )
diff --git a/ogr/ogrsf_frmts/sde/ogrsdedriver.cpp b/ogr/ogrsf_frmts/sde/ogrsdedriver.cpp
index e90f605..ac7a540 100644
--- a/ogr/ogrsf_frmts/sde/ogrsdedriver.cpp
+++ b/ogr/ogrsf_frmts/sde/ogrsdedriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsdedriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogrsdedriver.cpp 36090 2016-11-03 14:22:30Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSDEDriver class.
@@ -32,7 +32,7 @@
 #include "ogr_sde.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsdedriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrsdedriver.cpp 36090 2016-11-03 14:22:30Z rouault $");
 
 /************************************************************************/
 /*                            ~OGRSDEDriver()                            */
@@ -50,7 +50,7 @@ OGRSDEDriver::~OGRSDEDriver()
 const char *OGRSDEDriver::GetName()
 
 {
-    return "SDE";
+    return "OGR_SDE";
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/shape/shpopen.c b/ogr/ogrsf_frmts/shape/shpopen.c
index 61da0c5..6b257a5 100644
--- a/ogr/ogrsf_frmts/shape/shpopen.c
+++ b/ogr/ogrsf_frmts/shape/shpopen.c
@@ -1807,10 +1807,17 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 
 /* -------------------------------------------------------------------- */
 /*      Establish where we are going to put this record. If we are      */
-/*      rewriting and existing record, and it will fit, then put it     */
-/*      back where the original came from.  Otherwise write at the end. */
+/*      rewriting the last record of the file, then we can update it in */
+/*      place. Otherwise if rewriting an existing record, and it will   */
+/*      fit, then put it  back where the original came from.  Otherwise */
+/*      write at the end.                                               */
 /* -------------------------------------------------------------------- */
-    if( nShapeId == -1 || psSHP->panRecSize[nShapeId] < nRecordSize-8 )
+    if( nShapeId != -1 && psSHP->panRecOffset[nShapeId] +
+                        psSHP->panRecSize[nShapeId] + 8 == psSHP->nFileSize )
+    {
+        nRecordOffset = psSHP->panRecOffset[nShapeId];
+    }
+    else if( nShapeId == -1 || psSHP->panRecSize[nShapeId] < nRecordSize-8 )
     {
         unsigned int nExpectedSize = psSHP->nFileSize + nRecordSize;
         if( nExpectedSize < psSHP->nFileSize ) // due to unsigned int overflow
diff --git a/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h b/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
index 2fcd57b..d1ddae4 100644
--- a/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
+++ b/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sqlite.h 33821 2016-03-31 12:34:40Z rouault $
+ * $Id: ogr_sqlite.h 36600 2016-12-01 13:59:11Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/SQLite driver.
@@ -36,6 +36,7 @@
 #include "cpl_error.h"
 #include <map>
 #include <set>
+#include <vector>
 
 #ifdef HAVE_SPATIALITE
   #ifdef SPATIALITE_AMALGAMATION
@@ -259,7 +260,7 @@ class OGRSQLiteLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
 
     void                BuildFeatureDefn( const char *pszLayerName,
                                           sqlite3_stmt *hStmt,
-                                          const std::set<CPLString>& aosGeomCols,
+                                          const std::set<CPLString>* paosGeomCols,
                                           const std::set<CPLString>& aosIgnoredCols);
 
     void                ClearStatement();
@@ -774,6 +775,8 @@ class OGRSQLiteDataSource CPL_FINAL : public OGRSQLiteBaseDataSource
 
     void                SaveStatistics();
 
+    std::vector<OGRLayer*> apoInvisibleLayers;
+
   public:
                         OGRSQLiteDataSource();
                         ~OGRSQLiteDataSource();
@@ -792,6 +795,7 @@ class OGRSQLiteDataSource CPL_FINAL : public OGRSQLiteBaseDataSource
     virtual int         GetLayerCount() { return nLayers; }
     virtual OGRLayer   *GetLayer( int );
     virtual OGRLayer   *GetLayerByName( const char* );
+    OGRLayer           *GetLayerByNameNotVisible( const char* );
     virtual std::pair<OGRLayer*, IOGRSQLiteGetSpatialWhere*> GetLayerWithGetSpatialWhereByName( const char* pszName );
 
     virtual OGRLayer    *ICreateLayer( const char *pszLayerName,
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
index 29be14c..2b30658 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitedatasource.cpp 35568 2016-09-30 19:38:55Z rouault $
+ * $Id: ogrsqlitedatasource.cpp 37124 2017-01-12 16:25:54Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteDataSource class.
@@ -51,7 +51,7 @@
 static int bSpatialiteGlobalLoaded = FALSE;
 #endif
 
-CPL_CVSID("$Id: ogrsqlitedatasource.cpp 35568 2016-09-30 19:38:55Z rouault $");
+CPL_CVSID("$Id: ogrsqlitedatasource.cpp 37124 2017-01-12 16:25:54Z rouault $");
 
 /************************************************************************/
 /*                      OGRSQLiteInitOldSpatialite()                    */
@@ -289,6 +289,31 @@ void OGRSQLiteBaseDataSource::CloseDB()
     {
         sqlite3_close( hDB );
         hDB = NULL;
+
+        // If we opened the DB in read-only mode, there might be spurious
+        // -wal and -shm files that we can make disappear by reopening in
+        // read-write
+        VSIStatBufL sStat;
+        if( eAccess == GA_ReadOnly &&
+            VSIStatL( CPLSPrintf("%s-wal", m_pszFilename), &sStat) == 0 )
+        {
+            CPL_IGNORE_RET_VAL( sqlite3_open( m_pszFilename, &hDB ) );
+            if( hDB != NULL )
+            {
+                // Dummy request
+                int nRowCount = 0, nColCount = 0;
+                char** papszResult = NULL;
+                sqlite3_get_table( hDB,
+                                    "SELECT name FROM sqlite_master WHERE 0",
+                                    &papszResult, &nRowCount, &nColCount,
+                                    NULL );
+                sqlite3_free_table( papszResult );
+
+                sqlite3_close( hDB );
+                hDB = NULL;
+            }
+        }
+
     }
 
 #ifdef HAVE_SQLITE_VFS
@@ -334,8 +359,6 @@ OGRSQLiteDataSource::OGRSQLiteDataSource()
 OGRSQLiteDataSource::~OGRSQLiteDataSource()
 
 {
-    int         i;
-
     for( int iLayer = 0; iLayer < nLayers; iLayer++ )
     {
         if( papoLayers[iLayer]->IsTableLayer() )
@@ -348,12 +371,14 @@ OGRSQLiteDataSource::~OGRSQLiteDataSource()
 
     SaveStatistics();
 
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
+    for( size_t i = 0; i < apoInvisibleLayers.size(); i++ )
+        delete apoInvisibleLayers[i];
 
     CPLFree( papoLayers );
 
-    for( i = 0; i < nKnownSRID; i++ )
+    for( int i = 0; i < nKnownSRID; i++ )
     {
         if( papoSRS[i] != NULL )
             papoSRS[i]->Release();
@@ -702,7 +727,8 @@ int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn, int bRegisterOGR2SQLite
 
     int nRowCount = 0, nColCount = 0;
     char** papszResult = NULL;
-    sqlite3_get_table( hDB,
+    char* pszErrMsg = NULL;
+    rc = sqlite3_get_table( hDB,
                        "SELECT name, sql FROM sqlite_master "
                        "WHERE (type = 'trigger' OR type = 'view') AND ("
                        "sql LIKE '%%ogr_geocode%%' OR "
@@ -710,7 +736,32 @@ int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn, int bRegisterOGR2SQLite
                        "sql LIKE '%%ogr_GetConfigOption%%' OR "
                        "sql LIKE '%%ogr_SetConfigOption%%' )",
                        &papszResult, &nRowCount, &nColCount,
-                       NULL );
+                       &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        bool bIsWAL = false;
+        VSILFILE* fp = VSIFOpenL(m_pszFilename, "rb");
+        if( fp != NULL )
+        {
+            GByte byVal = 0;
+            VSIFSeekL(fp, 18, SEEK_SET);
+            VSIFReadL(&byVal, 1, 1, fp);
+            bIsWAL = byVal == 2;
+        }
+        if( bIsWAL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                "%s: this file is a WAL-enabled database. It cannot be opened "
+                "because it is presumably read-only or in a read-only directory.",
+                pszErrMsg);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "%s", pszErrMsg);
+        }
+        sqlite3_free( pszErrMsg );
+        return FALSE;
+    }
 
     sqlite3_free_table(papszResult);
     papszResult = NULL;
@@ -731,7 +782,7 @@ int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn, int bRegisterOGR2SQLite
     const char* pszSqliteJournal = CPLGetConfigOption("OGR_SQLITE_JOURNAL", NULL);
     if (pszSqliteJournal != NULL)
     {
-        char* pszErrMsg = NULL;
+        pszErrMsg = NULL;
 
         const char* pszSQL = CPLSPrintf("PRAGMA journal_mode = %s",
                                         pszSqliteJournal);
@@ -755,7 +806,7 @@ int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn, int bRegisterOGR2SQLite
         char** papszTokens = CSLTokenizeString2( pszSqlitePragma, ",", CSLT_HONOURSTRINGS );
         for(int i=0; papszTokens[i] != NULL; i++ )
         {
-            char* pszErrMsg = NULL;
+            pszErrMsg = NULL;
 
             const char* pszSQL = CPLSPrintf("PRAGMA %s", papszTokens[i]);
 
@@ -1722,6 +1773,12 @@ OGRLayer *OGRSQLiteDataSource::GetLayerByName( const char* pszLayerName )
     if( poLayer != NULL )
         return poLayer;
 
+    for( size_t i=0; i<apoInvisibleLayers.size(); ++i)
+    {
+        if( EQUAL(apoInvisibleLayers[i]->GetName(), pszLayerName) )
+            return apoInvisibleLayers[i];
+    }
+
     if( !OpenTable(pszLayerName) )
         return NULL;
 
@@ -1742,6 +1799,49 @@ OGRLayer *OGRSQLiteDataSource::GetLayerByName( const char* pszLayerName )
 }
 
 /************************************************************************/
+/*                    GetLayerByNameNotVisible()                        */
+/************************************************************************/
+
+OGRLayer *OGRSQLiteDataSource::GetLayerByNameNotVisible( const char* pszLayerName )
+
+{
+    {
+        OGRLayer* poLayer = GDALDataset::GetLayerByName(pszLayerName);
+        if( poLayer != NULL )
+            return poLayer;
+    }
+
+    for( size_t i=0; i<apoInvisibleLayers.size(); ++i)
+    {
+        if( EQUAL(apoInvisibleLayers[i]->GetName(), pszLayerName) )
+            return apoInvisibleLayers[i];
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create the layer object.                                        */
+/* -------------------------------------------------------------------- */
+    OGRSQLiteTableLayer *poLayer = new OGRSQLiteTableLayer( this );
+    if( poLayer->Initialize( pszLayerName, FALSE, FALSE) != CE_None )
+    {
+        delete poLayer;
+        return NULL;
+    }
+    CPLErrorReset();
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    poLayer->GetLayerDefn();
+    CPLPopErrorHandler();
+    if( CPLGetLastErrorType() != 0 )
+    {
+        CPLErrorReset();
+        delete poLayer;
+        return NULL;
+    }
+    apoInvisibleLayers.push_back(poLayer);
+
+    return poLayer;
+}
+
+/************************************************************************/
 /*                   GetLayerWithGetSpatialWhereByName()                */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
index d2e52c8..87a67d5 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogrsqlitelayer.cpp 35899 2016-10-24 11:56:25Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteLayer class, code shared between
@@ -42,7 +42,7 @@
 #include "ogr_sqlite.h"
 #include <cassert>
 
-CPL_CVSID("$Id: ogrsqlitelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrsqlitelayer.cpp 35899 2016-10-24 11:56:25Z rouault $");
 
 /************************************************************************/
 /*                           OGRSQLiteLayer()                           */
@@ -135,6 +135,7 @@ int OGRIsBinaryGeomCol( sqlite3_stmt *hStmt,
 {
     OGRGeometry* poGeometry = NULL;
     const int nBytes = sqlite3_column_bytes( hStmt, iCol );
+    int nBytesConsumed = 0;
     CPLPushErrorHandler(CPLQuietErrorHandler);
     /* Try as spatialite first since createFromWkb() can sometimes */
     /* interpret spatialite blobs as WKB for certain SRID values */
@@ -152,7 +153,8 @@ int OGRIsBinaryGeomCol( sqlite3_stmt *hStmt,
     }
     else if( OGRGeometryFactory::createFromFgf(
             (GByte*)sqlite3_column_blob( hStmt, iCol ),
-            NULL, &poGeometry, nBytes, NULL ) == OGRERR_NONE )
+            NULL, &poGeometry, nBytes, &nBytesConsumed ) == OGRERR_NONE &&
+             nBytes == nBytesConsumed )
     {
         eGeomFormat = OSGF_FGF;
     }
@@ -175,7 +177,7 @@ int OGRIsBinaryGeomCol( sqlite3_stmt *hStmt,
 
 void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
                                        sqlite3_stmt *hStmtIn,
-                                       const std::set<CPLString>& aosGeomCols,
+                                       const std::set<CPLString>* paosGeomCols,
                                        const std::set<CPLString>& aosIgnoredCols )
 
 {
@@ -228,7 +230,8 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
         {
             continue;
         }
-        if( aosGeomCols.find( CPLString(oField.GetNameRef()).tolower() ) != aosGeomCols.end() )
+        if( paosGeomCols != NULL &&
+            paosGeomCols->find( CPLString(oField.GetNameRef()).tolower() ) != paosGeomCols->end() )
         {
             OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
                 new OGRSQLiteGeomFieldDefn(oField.GetNameRef(), iCol);
@@ -398,7 +401,8 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
         }
 
         // Recognise some common geometry column names.
-        if( (EQUAL(oField.GetNameRef(),"wkt_geometry")
+        if( paosGeomCols == NULL &&
+            (EQUAL(oField.GetNameRef(),"wkt_geometry")
              || EQUAL(oField.GetNameRef(),"geometry")
              || STARTS_WITH_CI(oField.GetNameRef(), "asbinary(")
              || STARTS_WITH_CI(oField.GetNameRef(), "astext(")
@@ -467,7 +471,8 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
         }
 
         // SpatialLite / Gaia
-        if( EQUAL(oField.GetNameRef(),"GaiaGeometry")
+        if( paosGeomCols == NULL &&
+            EQUAL(oField.GetNameRef(),"GaiaGeometry")
             && (bAllowMultipleGeomFields || poFeatureDefn->GetGeomFieldCount() == 0) )
         {
             OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
@@ -479,7 +484,8 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
 
         // Recognize a geometry column from trying to build the geometry
         // Useful for OGRSQLiteSelectLayer
-        if( nColType == SQLITE_BLOB &&
+        if( paosGeomCols == NULL &&
+            nColType == SQLITE_BLOB &&
             (bAllowMultipleGeomFields || poFeatureDefn->GetGeomFieldCount() == 0) )
         {
             const int nBytes = sqlite3_column_bytes( hStmtIn, iCol );
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp
index 11ccb46..a1ce301 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqliteselectlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogrsqliteselectlayer.cpp 35899 2016-10-24 11:56:25Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteSelectLayer class, layer access to the results
@@ -34,7 +34,7 @@
 #include "swq.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrsqliteselectlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrsqliteselectlayer.cpp 35899 2016-10-24 11:56:25Z rouault $");
 
 /************************************************************************/
 /*                   OGRSQLiteSelectLayerCommonBehaviour()              */
@@ -69,7 +69,7 @@ OGRSQLiteSelectLayer::OGRSQLiteSelectLayer( OGRSQLiteDataSource *poDSIn,
     this->bAllowMultipleGeomFields = bAllowMultipleGeomFieldsIn;
 
     std::set<CPLString> aosEmpty;
-    BuildFeatureDefn( "SELECT", hStmtIn, aosEmpty, aosEmpty );
+    BuildFeatureDefn( "SELECT", hStmtIn, NULL, aosEmpty );
     SetDescription( "SELECT" );
 
     if( bUseStatementForGetNextFeature )
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
index e2f71cc..a665b88 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitetablelayer.cpp 35792 2016-10-17 19:19:40Z rouault $
+ * $Id: ogrsqlitetablelayer.cpp 35908 2016-10-24 12:31:58Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteTableLayer class, access to an existing table.
@@ -37,7 +37,7 @@
 
 #define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
 
-CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 35792 2016-10-17 19:19:40Z rouault $");
+CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 35908 2016-10-24 12:31:58Z rouault $");
 
 /************************************************************************/
 /*                        OGRSQLiteTableLayer()                         */
@@ -341,13 +341,14 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
         aosGeomCols.insert(pszGeomCol);
         std::set<CPLString> aosIgnoredCols(poDS->GetGeomColsForTable(pszTableName));
         aosIgnoredCols.erase(pszGeomCol);
-        BuildFeatureDefn( GetDescription(), hColStmt, aosGeomCols, aosIgnoredCols);
+        BuildFeatureDefn( GetDescription(), hColStmt, &aosGeomCols, aosIgnoredCols);
     }
     else
     {
         std::set<CPLString> aosIgnoredCols;
+        const std::set<CPLString>& aosGeomCols(poDS->GetGeomColsForTable(pszTableName));
         BuildFeatureDefn( GetDescription(), hColStmt,
-                          poDS->GetGeomColsForTable(pszTableName), aosIgnoredCols );
+                          (bIsVirtualShape) ? NULL : &aosGeomCols, aosIgnoredCols );
     }
     sqlite3_finalize( hColStmt );
 
@@ -2647,6 +2648,8 @@ OGRErr OGRSQLiteTableLayer::ISetFeature( OGRFeature *poFeature )
             poFeatureDefn->myGetGeomFieldDefn(iField)->eGeomFormat;
         if( eGeomFormat == OSGF_FGF )
             continue;
+        if( bNeedComma )
+            osCommand += ",";
 
         osCommand += "\"";
         osCommand += OGRSQLiteEscapeName( poFeatureDefn->GetGeomFieldDefn(iField)->GetNameRef());
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp
index d696463..881727d 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqliteviewlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogrsqliteviewlayer.cpp 36600 2016-12-01 13:59:11Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteViewLayer class, access to an existing spatialite view.
@@ -32,7 +32,7 @@
 #include "ogr_sqlite.h"
 #include <string>
 
-CPL_CVSID("$Id: ogrsqliteviewlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrsqliteviewlayer.cpp 36600 2016-12-01 13:59:11Z rouault $");
 
 /************************************************************************/
 /*                        OGRSQLiteViewLayer()                         */
@@ -140,11 +140,11 @@ OGRSQLiteLayer* OGRSQLiteViewLayer::GetUnderlyingLayer()
                                             osUnderlyingTableName.c_str(),
                                             osUnderlyingGeometryColumn.c_str());
             poUnderlyingLayer =
-                (OGRSQLiteLayer*) poDS->GetLayerByName(osNewUnderlyingTableName);
+                (OGRSQLiteLayer*) poDS->GetLayerByNameNotVisible(osNewUnderlyingTableName);
         }
         if( poUnderlyingLayer == NULL )
             poUnderlyingLayer =
-                (OGRSQLiteLayer*) poDS->GetLayerByName(osUnderlyingTableName);
+                (OGRSQLiteLayer*) poDS->GetLayerByNameNotVisible(osUnderlyingTableName);
     }
     return poUnderlyingLayer;
 }
@@ -239,7 +239,7 @@ CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn()
     std::set<CPLString> aosGeomCols;
     std::set<CPLString> aosIgnoredCols;
     aosGeomCols.insert(osGeomColumn);
-    BuildFeatureDefn( pszViewName, hColStmt, aosGeomCols, aosIgnoredCols );
+    BuildFeatureDefn( pszViewName, hColStmt, &aosGeomCols, aosIgnoredCols );
     sqlite3_finalize( hColStmt );
 
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp b/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
index 08d370e..a070fae 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrwfslayer.cpp 34401 2016-06-24 12:34:12Z rouault $
+ * $Id: ogrwfslayer.cpp 36904 2016-12-16 10:09:27Z rouault $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGRWFSLayer class.
@@ -34,7 +34,7 @@
 #include "cpl_http.h"
 #include "parsexsd.h"
 
-CPL_CVSID("$Id: ogrwfslayer.cpp 34401 2016-06-24 12:34:12Z rouault $");
+CPL_CVSID("$Id: ogrwfslayer.cpp 36904 2016-12-16 10:09:27Z rouault $");
 
 
 /************************************************************************/
@@ -1085,7 +1085,12 @@ OGRFeatureDefn * OGRWFSLayer::BuildLayerDefn(OGRFeatureDefn* poSrcFDefn)
         {
             return poFeatureDefn;
         }
-        poSrcFDefn = l_poDS->GetLayer(0)->GetLayerDefn();
+        OGRLayer* l_poLayer = l_poDS->GetLayer(0);
+        if( l_poLayer == NULL )
+        {
+            return poFeatureDefn;
+        }
+        poSrcFDefn = l_poLayer->GetLayerDefn();
         bGotApproximateLayerDefn = TRUE;
         /* We cannot trust width and precision based on a single feature */
         bUnsetWidthPrecision = TRUE;
@@ -1195,6 +1200,8 @@ OGRFeature *OGRWFSLayer::GetNextFeature()
             if (poBaseDS)
             {
                 poBaseLayer = poBaseDS->GetLayer(0);
+                if( poBaseLayer == NULL )
+                    return NULL;
                 poBaseLayer->ResetReading();
 
                 /* Check that the layer field definition is consistent with the one */
diff --git a/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp b/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
index ee6ee7c..1e45270 100644
--- a/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
+++ b/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrxlsxdatasource.cpp 35710 2016-10-13 07:21:17Z rouault $
+ * $Id: ogrxlsxdatasource.cpp 36555 2016-11-29 22:18:53Z rouault $
  *
  * Project:  XLSX Translator
  * Purpose:  Implements OGRXLSXDataSource class
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_time.h"
 
-CPL_CVSID("$Id: ogrxlsxdatasource.cpp 35710 2016-10-13 07:21:17Z rouault $");
+CPL_CVSID("$Id: ogrxlsxdatasource.cpp 36555 2016-11-29 22:18:53Z rouault $");
 
 namespace OGRXLSX {
 
@@ -952,7 +952,11 @@ void OGRXLSXDataSource::BuildLayer(OGRXLSXLayer* poLayer)
     const char* pszSheetFilename = poLayer->GetFilename().c_str();
     VSILFILE* fp = VSIFOpenL(pszSheetFilename, "rb");
     if (fp == NULL)
+    {
+        CPLDebug("XLSX", "Cannot open file %s for sheet %s",
+                 pszSheetFilename, poLayer->GetName());
         return;
+    }
 
     int bUpdatedBackup = bUpdated;
 
@@ -1270,8 +1274,21 @@ void OGRXLSXDataSource::startElementWBCbk(const char *pszNameIn,
             oMapRelsIdToTarget.find(pszId) != oMapRelsIdToTarget.end() )
         {
             papoLayers = (OGRLayer**)CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
-            papoLayers[nLayers++] = new OGRXLSXLayer(this,
-                CPLSPrintf("/vsizip/%s/xl/%s", pszName, oMapRelsIdToTarget[pszId].c_str()),
+            CPLString osFilename;
+            if( !oMapRelsIdToTarget[pszId].empty() &&
+                oMapRelsIdToTarget[pszId][0] == '/' )
+            {
+                // Is it an "absolute" path ? 
+                osFilename = "/vsizip/" + CPLString(pszName) +
+                             oMapRelsIdToTarget[pszId];
+            }
+            else
+            {
+                // or relative to the /xl subdirectory
+                osFilename = "/vsizip/" + CPLString(pszName) +
+                             CPLString("/xl/") + oMapRelsIdToTarget[pszId];
+            }
+            papoLayers[nLayers++] = new OGRXLSXLayer(this, osFilename,
                 pszSheetName);
         }
     }
diff --git a/port/cpl_config.h.in b/port/cpl_config.h.in
index 1795d08..2e82fbb 100644
--- a/port/cpl_config.h.in
+++ b/port/cpl_config.h.in
@@ -155,6 +155,9 @@
 /* Define to 1 if you have the statvfs' function. */
 #undef HAVE_STATVFS
 
+/* Define to 1 if you have the `statvfs64' function. */
+#undef HAVE_STATVFS64
+
 /* Define to 1 if you have the `lstat' function. */
 #undef HAVE_LSTAT
 
diff --git a/port/cpl_http.cpp b/port/cpl_http.cpp
index bc79823..10bf7e9 100644
--- a/port/cpl_http.cpp
+++ b/port/cpl_http.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_http.cpp 33646 2016-03-05 15:54:03Z goatbar $
+ * $Id: cpl_http.cpp 36551 2016-11-28 23:01:13Z rouault $
  *
  * Project:  libcurl based HTTP client
  * Purpose:  libcurl based HTTP client
@@ -44,7 +44,7 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions);
 
 #endif
 
-CPL_CVSID("$Id: cpl_http.cpp 33646 2016-03-05 15:54:03Z goatbar $");
+CPL_CVSID("$Id: cpl_http.cpp 36551 2016-11-28 23:01:13Z rouault $");
 
 // list of named persistent http sessions
 
@@ -148,6 +148,11 @@ static size_t CPLHdrWriteFct(void *buffer, size_t size, size_t nmemb, void *reqI
  *               504 HTTP error occurs. Default is 0. (GDAL >= 2.0)
  * <li>RETRY_DELAY=val, where val is the number of seconds between retry attempts.
  *                 Default is 30. (GDAL >= 2.0)
+ * <li>CAINFO=/path/to/bundle.crt. This is path to Certificate Authority (CA)
+ *     bundle file. By default, it will be looked in a system location. If
+ *     the CAINFO options is not defined, GDAL will also look if the CURL_CA_BUNDLE
+ *     environment variable is defined to use it as the CAINFO value, and as a
+ *     fallback to the SSL_CERT_FILE environment variable. (GDAL >= 2.1.3)</li>
  * </ul>
  *
  * Alternatively, if not defined in the papszOptions arguments, the TIMEOUT,
@@ -624,6 +629,20 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
         curl_easy_setopt(http_handle, CURLOPT_SSL_VERIFYHOST, 0L);
     }
 
+    // Custom path to SSL certificates.
+    const char* pszCAInfo = CSLFetchNameValue( papszOptions, "CAINFO" );
+    if (pszCAInfo == NULL)
+        // Name of environment variable used by the curl binary
+        pszCAInfo = CPLGetConfigOption("CURL_CA_BUNDLE", NULL);
+    if (pszCAInfo == NULL)
+        // Name of environment variable used by the curl binary (tested
+        // after CURL_CA_BUNDLE
+        pszCAInfo = CPLGetConfigOption("SSL_CERT_FILE", NULL);
+    if( pszCAInfo != NULL )
+    {
+        curl_easy_setopt(http_handle, CURLOPT_CAINFO, pszCAInfo);
+    }
+
     /* Set Referer */
     const char *pszReferer = CSLFetchNameValue(papszOptions, "REFERER");
     if (pszReferer != NULL)
diff --git a/port/cpl_vsil_unix_stdio_64.cpp b/port/cpl_vsil_unix_stdio_64.cpp
index a4a94b6..f634ad5 100644
--- a/port/cpl_vsil_unix_stdio_64.cpp
+++ b/port/cpl_vsil_unix_stdio_64.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_vsil_unix_stdio_64.cpp 34353 2016-06-16 08:23:41Z rouault $
+ * $Id: cpl_vsil_unix_stdio_64.cpp 36874 2016-12-15 01:53:28Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for Unix platforms with fseek64()
@@ -66,7 +66,7 @@
 #include <errno.h>
 #include <new>
 
-CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 34353 2016-06-16 08:23:41Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 36874 2016-12-15 01:53:28Z rouault $");
 
 #if defined(UNIX_STDIO_64)
 
@@ -659,12 +659,22 @@ GIntBig VSIUnixStdioFilesystemHandler::GetDiskFreeSpace( const char*
 {
     GIntBig nRet = -1;
 #ifdef HAVE_STATVFS
+
+#ifdef HAVE_STATVFS64
+    struct statvfs64 buf;
+    if( statvfs64(pszDirname, &buf) == 0 )
+    {
+        nRet = static_cast<GIntBig>(buf.f_frsize * static_cast<GUIntBig>(buf.f_bavail));
+    }
+#else
     struct statvfs buf;
     if( statvfs(pszDirname, &buf) == 0 )
     {
-        nRet = static_cast<GIntBig>(buf.f_frsize * buf.f_bavail);
+        nRet = static_cast<GIntBig>(buf.f_frsize * static_cast<GUIntBig>(buf.f_bavail));
     }
 #endif
+
+#endif
     return nRet;
 }
 
diff --git a/swig/include/perl/gdal_perl.i b/swig/include/perl/gdal_perl.i
index 4d026e9..c12d6c4 100644
--- a/swig/include/perl/gdal_perl.i
+++ b/swig/include/perl/gdal_perl.i
@@ -140,8 +140,8 @@ use Geo::OSR;
 # Note that the 1/100000 digits may be used to create more than one
 # CPAN release from one GDAL release.
 
-our $VERSION = '2.0102';
-our $GDAL_VERSION = '2.1.2';
+our $VERSION = '2.0103';
+our $GDAL_VERSION = '2.1.3';
 
 =pod
 
diff --git a/swig/include/perl/ogr_perl.i b/swig/include/perl/ogr_perl.i
index a65acbc..7ae6093 100644
--- a/swig/include/perl/ogr_perl.i
+++ b/swig/include/perl/ogr_perl.i
@@ -120,7 +120,7 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 %perlcode %{
 
 package Geo::OGR;
-our $VERSION = '2.0102'; # this needs to be the same as that in gdal_perl.i
+our $VERSION = '2.0103'; # this needs to be the same as that in gdal_perl.i
 
 sub Driver {
     return 'Geo::GDAL::Driver' unless @_;
@@ -1661,13 +1661,13 @@ sub Points {
             }
         } elsif ($t eq 'MultiLineString') {
             for my $l (@$points) {
-                my $linestring = Geo::OGR::Geometry->new('Point'.$postfix);
+                my $linestring = Geo::OGR::Geometry->new('LineString'.$postfix);
                 $linestring->Points($l);
                 $self->AddGeometryDirectly($linestring);
             }
         } elsif ($t eq 'MultiPolygon') {
             for my $p (@$points) {
-                my $polygon = Geo::OGR::Geometry->new('Point'.$postfix);
+                my $polygon = Geo::OGR::Geometry->new('Polygon'.$postfix);
                 $polygon->Points($p);
                 $self->AddGeometryDirectly($polygon);
             }
diff --git a/swig/include/python/gdal_python.i b/swig/include/python/gdal_python.i
index b6ad8ed..6138189 100644
--- a/swig/include/python/gdal_python.i
+++ b/swig/include/python/gdal_python.i
@@ -1,5 +1,5 @@
 /*
- * $Id: gdal_python.i 33573 2016-02-26 21:33:04Z rouault $
+ * $Id: gdal_python.i 37118 2017-01-12 12:15:16Z rouault $
  *
  * python specific code for gdal bindings.
  */
@@ -1332,7 +1332,7 @@ def DEMProcessingOptions(options = [], colorFilename = None, format = 'GTiff',
         if trigonometric:
             new_options += ['-trigonometric' ]
         if zeroForFlat:
-            new_options += ['zero_for_flat' ]
+            new_options += ['-zero_for_flat' ]
 
     return (GDALDEMProcessingOptions(new_options), colorFilename, callback, callback_data)
 
@@ -1528,6 +1528,7 @@ def Grid(destName, srcDS, **kwargs):
     return GridInternal(destName, srcDS, opts, callback, callback_data)
 
 def RasterizeOptions(options = [], format = None,
+         outputType = GDT_Unknown, 
          creationOptions = None, noData = None, initValues = None,
          outputBounds = None, outputSRS = None,
          width = None, height = None,
@@ -1540,6 +1541,7 @@ def RasterizeOptions(options = [], format = None,
         Keyword arguments are :
           options --- can be be an array of strings, a string or let empty and filled from other keywords.
           format --- output format ("GTiff", etc...)
+          outputType --- output type (gdal.GDT_Byte, etc...)
           creationOptions --- list of creation options
           outputBounds --- assigned output bounds: [minx, miny, maxx, maxy]
           outputSRS --- assigned output SRS
@@ -1570,6 +1572,8 @@ def RasterizeOptions(options = [], format = None,
         new_options = copy.copy(options)
         if format is not None:
             new_options += ['-of', format]
+        if outputType != GDT_Unknown:
+            new_options += ['-ot', GetDataTypeName(outputType) ]
         if creationOptions is not None:
             for opt in creationOptions:
                 new_options += ['-co', opt ]
diff --git a/swig/perl/lib/Geo/GDAL.pm b/swig/perl/lib/Geo/GDAL.pm
index f71e845..1719e7a 100644
--- a/swig/perl/lib/Geo/GDAL.pm
+++ b/swig/perl/lib/Geo/GDAL.pm
@@ -1003,8 +1003,8 @@ use Geo::OSR;
 # Note that the 1/100000 digits may be used to create more than one
 # CPAN release from one GDAL release.
 
-our $VERSION = '2.0102';
-our $GDAL_VERSION = '2.1.2';
+our $VERSION = '2.0103';
+our $GDAL_VERSION = '2.1.3';
 
 =pod
 
diff --git a/swig/perl/lib/Geo/OGR.pm b/swig/perl/lib/Geo/OGR.pm
index 3618973..fbacbf3 100644
--- a/swig/perl/lib/Geo/OGR.pm
+++ b/swig/perl/lib/Geo/OGR.pm
@@ -893,7 +893,7 @@ package Geo::OGR;
 
 
 package Geo::OGR;
-our $VERSION = '2.0102'; # this needs to be the same as that in gdal_perl.i
+our $VERSION = '2.0103'; # this needs to be the same as that in gdal_perl.i
 
 sub Driver {
     return 'Geo::GDAL::Driver' unless @_;
@@ -2233,13 +2233,13 @@ sub Points {
             }
         } elsif ($t eq 'MultiLineString') {
             for my $l (@$points) {
-                my $linestring = Geo::OGR::Geometry->new('Point'.$postfix);
+                my $linestring = Geo::OGR::Geometry->new('LineString'.$postfix);
                 $linestring->Points($l);
                 $self->AddGeometryDirectly($linestring);
             }
         } elsif ($t eq 'MultiPolygon') {
             for my $p (@$points) {
-                my $polygon = Geo::OGR::Geometry->new('Point'.$postfix);
+                my $polygon = Geo::OGR::Geometry->new('Polygon'.$postfix);
                 $polygon->Points($p);
                 $self->AddGeometryDirectly($polygon);
             }
diff --git a/swig/perl/t/geom.t b/swig/perl/t/geom.t
new file mode 100644
index 0000000..2d9b9ad
--- /dev/null
+++ b/swig/perl/t/geom.t
@@ -0,0 +1,60 @@
+use strict;
+use warnings;
+use v5.10;
+use Scalar::Util 'blessed';
+use Test::More tests => 13;
+BEGIN { use_ok('Geo::GDAL') };
+
+{
+    my $type = 'Point';
+    my $geom = Geo::OGR::Geometry->new(GeometryType => $type);
+    my $points = [1,2];
+    $geom->Points($points);
+    my $points2 = $geom->Points;
+    ok(is_deeply($points, $points2), "Set and get points of a $type");
+}
+
+{
+    my $type = 'MultiPoint';
+    my $geom = Geo::OGR::Geometry->new(GeometryType => $type);
+    my $points = [[1,2],[3,4]];
+    $geom->Points($points);
+    my $points2 = $geom->Points;
+    ok(is_deeply($points, $points2), "Set and get points of a $type");
+}
+
+{
+    my $type = 'LineString';
+    my $geom = Geo::OGR::Geometry->new(GeometryType => $type);
+    my $points = [[1,2],[3,4]];
+    $geom->Points($points);
+    my $points2 = $geom->Points;
+    ok(is_deeply($points, $points2), "Set and get points of a $type");
+}
+
+{
+    my $type = 'MultiLineString';
+    my $geom = Geo::OGR::Geometry->new(GeometryType => $type);
+    my $points = [[[1,2],[3,4]],[[5,6],[7,8]]];
+    $geom->Points($points);
+    my $points2 = $geom->Points;
+    ok(is_deeply($points, $points2), "Set and get points of a $type");
+}
+
+{
+    my $type = 'Polygon';
+    my $geom = Geo::OGR::Geometry->new(GeometryType => $type);
+    my $points = [[[1,2],[3,4]],[[5,6],[7,8]]];
+    $geom->Points($points);
+    my $points2 = $geom->Points;
+    ok(is_deeply($points, $points2), "Set and get points of a $type");
+}
+
+{
+    my $type = 'MultiPolygon';
+    my $geom = Geo::OGR::Geometry->new(GeometryType => $type);
+    my $points = [[[[1,2],[3,4]],[[5,6],[7,8]]],[[[1.1,2.2],[3.3,4.4]],[[5.5,6.6],[7.7,8.8]]]];
+    $geom->Points($points);
+    my $points2 = $geom->Points;
+    ok(is_deeply($points, $points2), "Set and get points of a $type");
+}
diff --git a/swig/python/osgeo/gdal.py b/swig/python/osgeo/gdal.py
index a1aac4a..7af2df1 100644
--- a/swig/python/osgeo/gdal.py
+++ b/swig/python/osgeo/gdal.py
@@ -732,7 +732,7 @@ def DEMProcessingOptions(options = [], colorFilename = None, format = 'GTiff',
         if trigonometric:
             new_options += ['-trigonometric' ]
         if zeroForFlat:
-            new_options += ['zero_for_flat' ]
+            new_options += ['-zero_for_flat' ]
 
     return (GDALDEMProcessingOptions(new_options), colorFilename, callback, callback_data)
 
@@ -928,6 +928,7 @@ def Grid(destName, srcDS, **kwargs):
     return GridInternal(destName, srcDS, opts, callback, callback_data)
 
 def RasterizeOptions(options = [], format = None,
+         outputType = GDT_Unknown, 
          creationOptions = None, noData = None, initValues = None,
          outputBounds = None, outputSRS = None,
          width = None, height = None,
@@ -940,6 +941,7 @@ def RasterizeOptions(options = [], format = None,
         Keyword arguments are :
           options --- can be be an array of strings, a string or let empty and filled from other keywords.
           format --- output format ("GTiff", etc...)
+          outputType --- output type (gdal.GDT_Byte, etc...)
           creationOptions --- list of creation options
           outputBounds --- assigned output bounds: [minx, miny, maxx, maxy]
           outputSRS --- assigned output SRS
@@ -970,6 +972,8 @@ def RasterizeOptions(options = [], format = None,
         new_options = copy.copy(options)
         if format is not None:
             new_options += ['-of', format]
+        if outputType != GDT_Unknown:
+            new_options += ['-ot', GetDataTypeName(outputType) ]
         if creationOptions is not None:
             for opt in creationOptions:
                 new_options += ['-co', opt ]
diff --git a/swig/python/scripts/gdal_calc.py b/swig/python/scripts/gdal_calc.py
index 7f1d766..eaf0e01 100755
--- a/swig/python/scripts/gdal_calc.py
+++ b/swig/python/scripts/gdal_calc.py
@@ -298,7 +298,7 @@ def doit(opts, args):
 
 ################################################################
 def main():
-    usage = "usage: %prog [-A <filename>] [--A_band] [-B...-Z filename] [other_options]"
+    usage = "usage: %prog [-A <filename>] [--A_band=n] [-B...-Z filename] [other_options]"
     parser = OptionParser(usage)
 
     # define options
diff --git a/swig/python/setup.py b/swig/python/setup.py
index e072cd1..6b0580a 100644
--- a/swig/python/setup.py
+++ b/swig/python/setup.py
@@ -7,13 +7,26 @@
 # Howard Butler hobu.inc at gmail.com
 
 
-gdal_version = '2.1.2'
+gdal_version = '2.1.3'
 
 import sys
 import os
 
 from glob import glob
 
+# If CXX is defined in the environment, it will be used to link the .so
+# but distutils will be confused if it is made of several words like 'ccache g++'
+# and it will try to use only the first word.
+# See https://lists.osgeo.org/pipermail/gdal-dev/2016-July/044686.html
+# Note: in general when doing "make", CXX will not be defined, unless it is defined as
+# an environment variable, but in that case it is the value of GDALmake.opt that
+# will be set, not the one from the environment that started "make" !
+# If no CXX environment variable is defined, then the value of the CXX variable
+# in GDALmake.opt will not be set as an environment variable
+if 'CXX' in os.environ and os.environ['CXX'].strip().find(' ') >= 0:
+    print('WARNING: "CXX=%s" was defined in the environment and contains more than one word. Unsetting it since that is incompatible of distutils' % os.environ['CXX'])
+    del os.environ['CXX']
+
 # ---------------------------------------------------------------------------
 # Switches
 # ---------------------------------------------------------------------------

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/gdal.git



More information about the Pkg-grass-devel mailing list