[gdal] 07/29: Imported Upstream version 2.0.0~beta2+dfsg

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Sun Jun 14 20:19:44 UTC 2015


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

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

commit 496aca218879ac8bc513424e1119faf4185fa479
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sat Jun 13 21:23:49 2015 +0200

    Imported Upstream version 2.0.0~beta2+dfsg
---
 GNUmakefile                                        |   1 +
 NEWS                                               |  49 +-
 VERSION                                            |   2 +-
 alg/gdal_crs.c                                     |  13 +-
 alg/gdal_rpc.cpp                                   | 277 +++++-
 alg/gdal_tps.cpp                                   |   7 +-
 alg/gdalgeoloc.cpp                                 |   7 +-
 alg/gdaltransformer.cpp                            |  37 +-
 alg/gdalwarper.cpp                                 |   7 +-
 apps/GNUmakefile                                   |   2 +-
 apps/gdal_utilities.dox                            |   7 +-
 apps/gdalinfo.c                                    | 994 +++++++++++++++++----
 apps/gdalwarp.cpp                                  | 282 ++++--
 apps/makefile.vc                                   |   2 +-
 apps/ogr2ogr.cpp                                   |  45 +-
 apps/ogr_utilities.dox                             |   7 +-
 configure                                          |  42 +-
 configure.in                                       |   3 +-
 frmts/blx/blx.c                                    |   2 +
 frmts/gif/gifabstractdataset.cpp                   |  36 +-
 frmts/gif/gifabstractdataset.h                     |   6 +-
 frmts/gtiff/geotiff.cpp                            |  26 +-
 frmts/hdf4/hdf4dataset.cpp                         |  10 +-
 frmts/hdf4/hdf4imagedataset.cpp                    |  47 +-
 frmts/hfa/hfadataset.cpp                           |  15 +-
 frmts/jpeg2000/jpeg2000dataset.cpp                 |   6 +-
 frmts/netcdf/netcdfdataset.cpp                     |  11 +-
 frmts/pcraster/pcrasterdataset.cpp                 |  10 +-
 frmts/pcraster/pcrasterdataset.h                   |   6 +-
 frmts/pcraster/pcrasterrasterband.cpp              |  68 +-
 frmts/pcraster/pcrasterrasterband.h                |  10 +-
 frmts/til/tildataset.cpp                           |  10 +-
 frmts/vrt/vrtdataset.cpp                           |  24 +-
 frmts/vrt/vrtsourcedrasterband.cpp                 |   8 +-
 frmts/vrt/vrtsources.cpp                           |  87 +-
 frmts/wms/frmt_wms.html                            |  17 +-
 gcore/GNUmakefile                                  |   2 +-
 gcore/gdal.h                                       |   5 +-
 gcore/gdal_mdreader.cpp                            |  88 +-
 gcore/gdal_mdreader.h                              |  29 +-
 gcore/gdal_rat.cpp                                 | 117 ++-
 gcore/gdal_rat.h                                   |   3 +-
 gcore/gdal_version.h                               |   4 +-
 gcore/gdaldataset.cpp                              |  24 +-
 gcore/gdaldriver.cpp                               |   9 +-
 gcore/gdaljp2metadata.cpp                          | 105 ++-
 gcore/gdaljp2metadata.h                            |   5 +-
 gcore/makefile.vc                                  |   2 +-
 gcore/mdreader/GNUmakefile                         |   4 +-
 gcore/mdreader/makefile.vc                         |   8 +-
 gcore/mdreader/reader_alos.cpp                     | 405 +++++++++
 gcore/mdreader/{reader_geo_eye.h => reader_alos.h} |  44 +-
 gcore/mdreader/reader_digital_globe.h              |  20 +-
 gcore/mdreader/reader_eros.cpp                     | 286 ++++++
 gcore/mdreader/{reader_geo_eye.h => reader_eros.h} |  35 +-
 gcore/mdreader/reader_geo_eye.cpp                  |   9 +-
 gcore/mdreader/reader_geo_eye.h                    |  14 +-
 gcore/mdreader/reader_kompsat.cpp                  | 277 ++++++
 .../{reader_pleiades.h => reader_kompsat.h}        |  35 +-
 gcore/mdreader/reader_landsat.cpp                  |  12 +-
 gcore/mdreader/reader_landsat.h                    |  16 +-
 gcore/mdreader/reader_orb_view.h                   |  14 +-
 gcore/mdreader/reader_pleiades.cpp                 |   9 +-
 gcore/mdreader/reader_pleiades.h                   |  12 +-
 gcore/mdreader/reader_rapid_eye.cpp                | 155 ++++
 .../{reader_pleiades.h => reader_rapid_eye.h}      |  35 +-
 gcore/mdreader/reader_rdk1.h                       |  10 +-
 gcore/mdreader/reader_spot.cpp                     | 315 +++++++
 .../mdreader/{reader_pleiades.h => reader_spot.h}  |  40 +-
 gcore/rasterio.cpp                                 |   8 +-
 man/man1/gdal-config.1                             |   4 +-
 man/man1/gdal2tiles.1                              |   4 +-
 man/man1/gdal_calc.1                               |   4 +-
 man/man1/gdal_contour.1                            |   4 +-
 man/man1/gdal_edit.1                               |   4 +-
 man/man1/gdal_fillnodata.1                         |   4 +-
 man/man1/gdal_grid.1                               |   4 +-
 man/man1/gdal_merge.1                              |   4 +-
 man/man1/gdal_polygonize.1                         |   4 +-
 man/man1/gdal_proximity.1                          |   4 +-
 man/man1/gdal_rasterize.1                          |   4 +-
 man/man1/gdal_retile.1                             |   4 +-
 man/man1/gdal_sieve.1                              |   4 +-
 man/man1/gdal_translate.1                          |   4 +-
 man/man1/gdal_utilities.1                          |   4 +-
 man/man1/gdaladdo.1                                |   4 +-
 man/man1/gdalbuildvrt.1                            |   4 +-
 man/man1/gdalcompare.1                             |   4 +-
 man/man1/gdaldem.1                                 |   4 +-
 man/man1/gdalinfo.1                                |   8 +-
 man/man1/gdallocationinfo.1                        |   4 +-
 man/man1/gdalmanage.1                              |   4 +-
 man/man1/gdalmove.1                                |   4 +-
 man/man1/gdalsrsinfo.1                             |   4 +-
 man/man1/gdaltindex.1                              |   4 +-
 man/man1/gdaltransform.1                           |   4 +-
 man/man1/gdalwarp.1                                |   4 +-
 man/man1/nearblack.1                               |   4 +-
 man/man1/ogr2ogr.1                                 |   8 +-
 man/man1/ogr_utilities.1                           |   4 +-
 man/man1/ogrinfo.1                                 |   4 +-
 man/man1/ogrlineref.1                              |   4 +-
 man/man1/ogrtindex.1                               |   4 +-
 man/man1/pct2rgb.1                                 |   4 +-
 man/man1/rgb2pct.1                                 |   4 +-
 ogr/ogrsf_frmts/csv/drv_csv.html                   |   9 +-
 ogr/ogrsf_frmts/csv/ogr_csv.h                      |   7 +-
 ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp           |  28 +-
 ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp               |  15 +-
 ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp                |  59 +-
 ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp         |  10 +-
 ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp             | 156 ++--
 ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp              |  18 +-
 ogr/ogrsf_frmts/filegdb/drv_filegdb.html           |   4 +-
 ogr/ogrsf_frmts/filegdb/ogr_fgdb.h                 |   7 +-
 ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp | 143 ++-
 ogr/ogrsf_frmts/generic/ogremulatedtransaction.h   |  20 -
 ogr/ogrsf_frmts/geojson/libjson/json_object.h      |  21 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp       |  13 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h         |  12 +-
 ogr/ogrsf_frmts/gml/drv_gml.html                   |  28 +-
 ogr/ogrsf_frmts/gml/gmlhandler.cpp                 |  39 +-
 ogr/ogrsf_frmts/gml/gmlreader.cpp                  |   6 +-
 ogr/ogrsf_frmts/gml/gmlreaderp.h                   |   8 +-
 ogr/ogrsf_frmts/gml/gmlregistry.cpp                |  16 +-
 ogr/ogrsf_frmts/gml/gmlregistry.h                  |   5 +-
 ogr/ogrsf_frmts/gml/ogr_gml.h                      |   4 +-
 ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp           |  48 +-
 ogr/ogrsf_frmts/gml/ogrgmldriver.cpp               |  31 +-
 ogr/ogrsf_frmts/gpkg/drv_geopackage.html           |  14 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp   |   5 +
 ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp        |   6 +
 ogr/ogrsf_frmts/gpsbabel/drv_gpsbabel.html         |   1 +
 ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h            |   5 +-
 ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp |  32 +-
 ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp     | 131 ++-
 ogr/ogrsf_frmts/ili/drv_ili.html                   |  33 +-
 ogr/ogrsf_frmts/ili/ogrili1layer.cpp               |   6 +-
 ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html |  10 +-
 ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h    |  13 +-
 .../mssqlspatial/ogrmssqlspatialdatasource.cpp     | 135 +--
 .../mssqlspatial/ogrmssqlspatiallayer.cpp          |   5 +-
 .../mssqlspatial/ogrmssqlspatialtablelayer.cpp     | 195 ++--
 ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp       |  11 +-
 ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp       |  62 +-
 ogr/ogrsf_frmts/openfilegdb/filegdbtable.h         |   5 +-
 .../openfilegdb/ogropenfilegdblayer.cpp            |  18 +-
 ogr/ogrsf_frmts/osm/drv_osm.html                   |  16 +
 ogr/ogrsf_frmts/osm/ogr_osm.h                      |   6 +-
 ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp           |  28 +-
 ogr/ogrsf_frmts/osm/ogrosmdriver.cpp               |  15 +-
 ogr/ogrsf_frmts/plscenes/drv_plscenes.html         |   6 +-
 ogr/ogrsf_frmts/plscenes/ogr_plscenes.h            |   8 +-
 ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp    |  45 +-
 ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp      |  59 +-
 ogr/ogrsf_frmts/shape/shape2ogr.cpp                |   6 +-
 ogr/ogrsf_frmts/wfs/drv_wfs.html                   |  12 +
 ogr/ogrsf_frmts/wfs/ogr_wfs.h                      |  11 +-
 ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp           |  19 +-
 ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp               |   9 +-
 ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp                |  65 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp   | 121 ++-
 ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h     |  33 +-
 port/cpl_csv.cpp                                   |  18 +-
 swig/csharp/gdal/Gdal.cs                           |   5 +-
 swig/csharp/gdal/GdalPINVOKE.cs                    |   2 +-
 swig/csharp/gdal/gdal_wrap.cpp                     |  34 +-
 swig/include/Band.i                                |  48 +-
 swig/include/cpl.i                                 |  20 +-
 swig/include/csharp/typemaps_csharp.i              |   4 +-
 swig/include/gdal.i                                |   4 +-
 swig/include/java/typemaps_java.i                  |   4 +-
 swig/include/perl/gdal_perl.i                      |  83 +-
 swig/include/perl/typemaps_perl.i                  | 125 ++-
 swig/include/python/typemaps_python.i              |   4 +-
 swig/perl/cr.dox                                   |   2 +-
 swig/perl/cv.dox                                   |   2 +-
 swig/perl/gdal_wrap.cpp                            | 212 +++--
 swig/perl/index.dox                                |   4 +-
 swig/perl/lib/Geo/GDAL.dox                         |   2 +-
 swig/perl/lib/Geo/GDAL.pm                          |  83 +-
 swig/perl/lib/Geo/OGR.dox                          |  20 +-
 swig/perl/lib/Geo/OSR.dox                          |   2 +-
 swig/perl/transform.dox                            |   4 +-
 swig/python/extensions/gdal_wrap.cpp               |  33 +-
 swig/python/osgeo/gdal.py                          |  10 +-
 swig/python/samples/README                         |   2 +
 swig/python/samples/gcps2ogr.py                    |  83 ++
 swig/python/scripts/gdal_merge.py                  |  28 +-
 189 files changed, 5631 insertions(+), 1547 deletions(-)

diff --git a/GNUmakefile b/GNUmakefile
index ca8f4dc..999abd0 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -124,6 +124,7 @@ docs:
 	cp doc/images/*.* html
 	cp doc/grid/*.png html
 	cp frmts/*.html frmts/*/frmt_*.html html
+	cp frmts/openjpeg/*.xml html
 	cp frmts/wms/frmt_*.xml html
 	cp ogr/ogrsf_frmts/*/drv_*.html html
 	cp ogr/ogrsf_frmts/ogr_formats.html html
diff --git a/NEWS b/NEWS
index 41c0389..1a4f368 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-= GDAL/OGR 2.0 Release Notes (to r29147) =
+= GDAL/OGR 2.0 Release Notes (to r29246) =
 
 ***** Work in progress ***** 
 
@@ -25,7 +25,7 @@
      - GDAL and OGR PDF drivers are unified into a single one
      - GDAL and OGR PCIDSK drivers are unified into a single one
  * RFC 49: Add support for curve geometries (http://trac.osgeo.org/gdal/wiki/rfc49_curve_geometries)
-   In OGR core, and GML, NAS, PostgreSQL, PGDUMP, GPKG, SQLite, VFK, VRT drivers
+   In OGR core, and GML, NAS, PostgreSQL, PGDUMP, GPKG, SQLite, VFK, VRT, Interlis drivers
  * RFC 50: Add support for OGR field subtypes (http://trac.osgeo.org/gdal/wiki/rfc50_ogr_field_subtype)
    In OGR core, OGR SQL, swig bindings, CSV, FileGDB, GeoJSON, GML, GPKG, OpenFileGDB, PG, PGDump, SQLite, VRT
  * RFC 51: RasterIO() improvements : resampling and progress callback (http://trac.osgeo.org/gdal/wiki/rfc51_rasterio_resampling_progress)
@@ -59,6 +59,7 @@ Build(Unix):
  * Make sure $(GDAL_INCLUDE) is first to avoid being confused by GDAL headers of a previous version elsewhere in the include path (#5664)
  * Always use stat rather than stat64 for Mac OSX in AC_UNIX_STDIO_64. (#5780, #5414).
  * Add support for ECW SDK 5.1 (#5390)
+ * Do not enable Python bindings if PYTHON env variable is set without --with-python being explicitely specified (#5956)
 
 Build(Windows):
  * PDF: fix compilation issue with Visual Studio 2012 (#5744)
@@ -103,7 +104,7 @@ Port:
  * CPLHexToBinary(): faster implementation (#5812)
 
 Core:
- * Add imagery (satellite or aerial) metadata support (DigitalGlobe, GeoEye, OrbView, Landsat, Pleiades, Resurs-DK1).
+ * Add imagery (satellite or aerial) metadata support (Alos, DigitalGlobe, Eros, GeoEye, OrbView, Landsat, Pleiades, Resurs-DK1, Spot/Formosat).
  * Reduce lock contention on the global cache mutex and make it possible to use spin lock instead with GDAL_RB_LOCK_TYPE=SPIN
  * EXIF reader: fix memleak in error code path
  * EXIF reader: add missing validation for some data types (#3078)
@@ -114,10 +115,12 @@ Core:
  * GDALJP2AbstractDataset: implement GetFileList() to report .wld/.j2w if used
  * GMLJP2: be robust when parsing GMLJP2 content that has nul character instead of \n (#5760)
  * GMLJP2: add missing rangeParameters element to validate against GMLJP2 schema (#5707)
+ * GMLJP2: write non null bounding box at root of FeatureCollection (#5697)
  * GMLJP2: SRS export as GML: output XML definition of a SRS as a GML 3.1.1 compliant Dictionary (#5697)
  * GMLJP2: when setting GDAL_JP2K_ALT_OFFSETVECTOR_ORDER=TRUE write it as a XML comment so that we can interpret the OffsetVector elements correctly on reading
  * GMLJP2: when parsing a GMLJP2 box, accept srsName found on gml:RectifiedGrid if not found on origin.Point, so as to be compatible with the example of DGIWG_Profile_of_JPEG2000_for_Georeferenced_Imagery.pdf (#5697)
  * GMLJP2: add compatibility with GMLJP2 v2.0 where SRS is expressed as CRS URL
+ * GMLJP2: on reading, don't do axis inversation if there's an explicit axisName requesting easting, northing order (#5960); also strip axis order in reported SRS
  * JP2Boxes: add null terminated byte to GDAL XML, XML or XMP boxes
  * Add GDALGetJPEG2000Structure() (#5697)
  * GDALMultiDomainMetadata::XMLInit(): when importing XML metadata, erase the existing document to replace it with the new one
@@ -137,7 +140,8 @@ Core:
 Algorithms:
  * RPC transformer: fix near interpolation in RPC DEM (#5553)
  * RPC transformer: take into account nodata in RPC DEM (#5680)
- * RPC transform: add RPC_DEM_MISSING_VALUE transformer option to avoid failure when there's no DEM at the transformed point (#5730)
+ * RPC transformer: add RPC_DEM_MISSING_VALUE transformer option to avoid failure when there's no DEM at the transformed point (#5730)
+ * RPC transformer: in DEM mode, implement optimization, in specific conditions (input points at same longitude, DEM in EPSG:4326) to extract several elevations at a time
  * TPS transformer: fix crash if the forward or backward transform cannot be computed (#5588)
  * OpenCL warper: remove unused variable in bilinear resampling that can cause compilation error (#5518)
  * OpenCL wraper: fix code compilation with NVIDIA OpenCL (#5772)
@@ -162,6 +166,7 @@ Algorithms:
 Utilities:
  * gdalinfo: display extra metadata domains attached to band, and refactor code a bit (#5542)
  * gdalinfo: add -oo option per RFC 46
+ * gdalinfo: add -json switch (partial implementation of RFC 44)
  * gdaladdo: add -oo option per RFC 46
  * gdaladdo: add warning when subsampling factor 1 specified
  * gdal_translate: add -oo option per RFC 46
@@ -180,6 +185,7 @@ Utilities:
  * gdalwarp: increase GDAL_MAX_DATASET_POOL_SIZE default value to 450. (#5828)
  * gdalwarp: do not preserve NODATA_VALUES metadata item in output dataset if adding an alpha channel with -dstalpha
  * gdalwarp: fix '-dstnodata none' to avoid read of uninitialized values (#5915)
+ * gdalwarp: make -crop_to_cutline densify cutline in source SRS before reprojecting it to target SRS (#5951)
  * gdaldem: avoid too large files to be produced when using -co COMPRESS=xxxx -co TILED=YES (#5678)
  * gdallocationinfo: add -oo option
  * gdaltransform: add a -output_xy flag to restrict output coordinates to 'x y' only
@@ -192,6 +198,7 @@ Utilities:
  * gdal_retile.py: fix to make it work with input images of different resolutions (#5749)
  * gdal_retile.py: implement progress bar (#5750)
  * gdal_merge.py: add timing information in verbose output
+ * gdal_merge.py: take into account alpha band to avoid writing zones of source images that are fully transparent (#3669)
  * gdal2tiles.py: fix inverted long/lat in BoundingBox and Origin elements of tilemapresource.xml (#5336)
  * pct2rgb.py: make it work with color tables with less than 256 entries (#5555)
  * gdal_fillnodata.py: FillNodata: copy no data value to destination band when creating a dataset (if available) (#4625)
@@ -206,6 +213,7 @@ Python samples:
  * Added dump_jp2.py
  * Added validate_jp2.py
  * Added build_jp2.py
+ * Added gcps2ogr.py
  * tolatlong.py: report error when operating on a non-georeferenced dataset
 
 AAIGRID:
@@ -247,6 +255,7 @@ GIF driver:
  * fix crash on images without color table (#5792)
  * fix reading of interlaced images with giflib >= 5.0
  * validate the size of the graphic control extension block (#5793)
+ * implement GetFileList() to report worldfile
 
 GRASS driver:
  * GRASS 7.0.0 support (#5852)
@@ -292,6 +301,7 @@ Fixes:
  * clean spurious spaces when reading values from _RPC.TXT
  * serialize RPC in PAM .aux.xml file if using PROFILE != GDALGeoTIFF and RPB = NO
  * fix clearing of GCPs (#5945)
+ * avoid generated corrupted right-most and bottom-most tiles for 12-bit JPEG-compressed (#5971)
 
 GRASS driver:
  * fix compilation issues against GRASS 7
@@ -299,6 +309,8 @@ GRASS driver:
 HDF4 driver:
  * Add configuration support to be able to open more files simultaneously
  * Add class suffix to the parameter name when parsing HDF-EOS objects.
+ * Fix AnyTypeToDouble() to use proper type (int instead of long) to work with DFNT_INT32/DFNT_UINT32 on 64-bit Linux (#5965)
+ * MODIS: Set more correct values for PIXEL_/LINE_ OFFSET/STEP by comparing longitude and latitude subdatasets dimensions with main subdataset dimensions
 
 HDF5 driver:
  * avoid opening BAG files in the case HDF5 and BAG are plugins, and HDF5 is registered before BAG
@@ -306,6 +318,7 @@ HDF5 driver:
 HFA driver:
  * fix recognition of Hotine Mercator Azimuth Center in Imagine format (and Swisstopo GeoTIFF) (#5551)
  * fix various hangs on invalid files
+ * read projection even when it does not contain datum information (#4659)
 
 HTTP driver/wrapper:
   * make it work with vector files too
@@ -403,6 +416,7 @@ NetCDF driver:
  * Force block size to 1 scanline for bottom-up datasets if nBlockYSize != 1 (#5291)
  * Fix computation of inverse flattening (#5858)
  * In case the netCDF driver is registered before the GMT driver, avoid opening GMT files
+ * Fix crash on opening a NOAA dataset (#5962)
 
 NGSGEOID driver:
  * make Identify() more restrictive
@@ -423,6 +437,7 @@ PCIDSK driver:
 PCRaster driver:
  * Allign libcsf code with PCRaster raster format code (#5843)
  * Implement Create() (#5844)
+ * Improve handling of no-data value (#5953)
 
 PDF driver:
  * add compatibility with Poppler 0.31.0
@@ -460,10 +475,14 @@ VRT driver:
  * do not output empty <Metadata> node on VRTDataset and VRTRasterBand elements
  * fix rounding of output window size on VRTSimpleSource (#5874)
  * add trick to make relativeToVRT works for a VRT-in-VRT
+ * VRT: add more checks to CheckCompatibleForDatasetIO() to avoid issues with overview bands (#5954)
 
 USGSDEM driver:
  * take into account horizontal unit = ft in the UTM case (#5819)
 
+TIL driver:
+ * fix half pixel shift in geo registration (#5961)
+
 WEBP driver:
  * Lazy uncompressed buffer allocation and optimize band-interleaved IRasterIO() for whole image reading
 
@@ -515,6 +534,8 @@ Utilities:
  * ogr2ogr: when copying a layer that has a source integer/integer64 field with same name as target FID column, avoid creating it into target layer and use its content as the FID value (#5845)
  * ogr2ogr: in non-append mode, if target layer has a FID creation option, reuse source FID name and source FIDs, unless -unsetFid is specified (#5845)
  * ogr2ogr: copy source dataset and layer metadata, unless disabled by -nomd. Additionnal dataset metadata can be set with -mo KEY=VALUE
+ * ogr2ogr: add -ds_transaction to force dataset transactions, mainly for FileGDB driver
+ * ogr2ogr: fix crash with -clipdst when a reprojection fails before (#5973)
  * ogrlineref: fix project if reper lies on first point or last point of line
 
 Other:
@@ -549,6 +570,7 @@ CSV driver:
  * add QUOTED_FIELDS_AS_STRING open option that default to NO. So by default, if AUTODETECT_TYPE=YES, the content of quoted fields will be tested for real, integer,... data types
  * fix to avoid truncation of WKT geometries to 8000 characters (#5508)
  * fix segfault when reading allCountries.txt of geonames.org (#5668)
+ * accept space as separator as input/output, and add MERGE_SEPARATOR=YES/NO open option
 
 DXF driver:
  * improve TestCapability(ODsCCreateLayer)
@@ -562,6 +584,7 @@ FileGDB driver:
  * fix CreateFeature() to work when a esriFieldTypeGlobalID field is not set
  * report width of string fields (#5806)
  * add compatibility with FileGDB SDK v1.4
+ * enable bulk load on newly created layers
 
 GeoJSON driver:
  * implement Date/Time/DateTime field type detection
@@ -575,6 +598,7 @@ GeoJSON driver:
  * internal libjson-c: Fix to read floating point numbers in non C locale (#5461)
  * improve TestCapability(ODsCCreateLayer)
  * make string comparison for authority name case insensitive so as to recognize lowercase 'epsg' (#4995)
+ * support reading Feature without geometry field
 
 GeoRSS driver:
  * fix to parse ATOM feed documents with atom: namespace (#5871)
@@ -584,7 +608,7 @@ GME driver:
 
 GML driver:
  * add XSD=filename open option
- * add a FORCE_SRS_DETECTION open option
+ * add FORCE_SRS_DETECTION, INVERT_AXIS_ORDER_IF_LAT_LONG, CONSIDER_EPSG_AS_URN, READ_MODE, EXPOSE_GML_ID, EXPOSE_FID, DOWNLOAD_SCHEMA and REGISTRY open options
  * fix bug that prevented multiple instanciation of the reader with Xerces backend (#5571)
  * parse correctly GML geometries whose srsDimension attribue is on top-level geometry element and not on posList (#5606)
  * add datasource option SRSDIMENSION_LOC=GEOMETRY to be able to write srsDimension attribute on top level geometry element, default on posList unchanged (#5066)
@@ -604,6 +628,7 @@ GML driver:
  * various fixes to better deal with ArcByCenterPoint() as found in FAA AIXML files
  * make Expat parser accept trailing nul characters
  * correctly record path to attribute in case of attribute located on a nested element when .gfs is created with GML_ATTRIBUTES_TO_OGR_FIELDS=YES
+ * fix GML_ATTRIBUTES_TO_OGR_FIELDS=YES to work correctly with xlink:href too (#5970
 
 GPKG driver:
  * add support for non-spatial layers via the gdal_aspatial extension (#5521)
@@ -630,6 +655,11 @@ GPKG driver:
  * recognize both GeomCollection and GeometryCollection as possible values, until GeoPackage SWG clears what is the official value
  * escape all column names in SQL (#5520)
  * accept geometries with Spatialite format, that can be returned with issuing a SQL request using spatialite functions
+ * enable Spatialite 4.3 'amphibious' mode to avoid explicit cast to Spatialite geometries
+
+GPSBabel driver:
+ * automatically open .igc files, implement Identify() and add open options
+ * advertize creation option
 
 GTM driver:
  * declare OLCCreateField and OLCSequentialWrite capabilities
@@ -683,6 +713,7 @@ MSSQLSpatial driver:
  * Fix crash if the tablename is specified in the connection string (#5826)
  * Include geometry column name in Update statement (#5930)
  * Implement FID layer creation option (#5816)
+ * Fix issue when removing an MSSQL spatial layer
 
 MySQL:
  * thread-safe initialization of mysql client library (#5528)
@@ -730,10 +761,14 @@ OpenFileGDB driver:
  * report width of string fields (#5806)
  * try to deal more gracefully with inconsistent nValidRecordCount vs nTotalRecordCount values (#5842)
  * report 25D layer geometry type on FileGDB v9 tables when relevant
+ * optimize sequential reading of sparse layers
+ * avoid warning when opening a00000004.gdbtable
+ * disable feature count optimization with IS NOT NULL on an index column
 
 OSM driver:
  * add mechanism to compute fields from other fields/tags with SQL expressions. Apply it for z_order on lines layer
  * fix random crash, particularly on MacOSX (#5465)
+ * add CONFIG_FILE, USE_CUSTOM_INDEXING, COMPRESS_NODES, MAX_TMPFILE_SIZE and INTERLEAVED_READING open options
 
 PG driver:
  * use COPY mode by default (unless PG_USE_COPY is set to NO) when inserting features in a newly create table (#5460)
@@ -824,6 +859,7 @@ WFS driver:
  * automatically enable paging if WFS 2.0 capabilities report paging support
  * evaluate SELECT with JOIN on server-side for a Join-capable WFS 2.0 server
  * add a TRUST_CAPABILITIES_BOUNDS open option, that can be set to YES to trust layer bounds declared in GetCapabilities response, for faster GetExtent() runtime (#4041)
+ * add INVERT_AXIS_ORDER_IF_LAT_LONG, CONSIDER_EPSG_AS_URN open options
  * add capability to use spatial functions ST_xxxxx() as server-side filters
  * add dataset and layer metadata
  * allow SELECT with several ORDER BY columns
@@ -834,6 +870,9 @@ WFS driver:
 XLSX driver:
  * fix column numbering when there are more than 26 columns (#5774)
 
+XPlane driver:
+ * add support for Taxi Location 1300 record found in V1000
+
 == SWIG Language Bindings ==
 
 All bindings:
diff --git a/VERSION b/VERSION
index 57d7910..d0cb2f2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0.0beta1
+2.0.0beta2
diff --git a/alg/gdal_crs.c b/alg/gdal_crs.c
index 24a8553..8f0e74c 100644
--- a/alg/gdal_crs.c
+++ b/alg/gdal_crs.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_crs.c 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: gdal_crs.c 29207 2015-05-18 17:23:45Z mloskot $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Implemention of the GDALTransformer wrapper around CRS.C functions
@@ -59,7 +59,7 @@
 #include "cpl_string.h"
 #include "cpl_atomic_ops.h"
 
-CPL_CVSID("$Id: gdal_crs.c 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: gdal_crs.c 29207 2015-05-18 17:23:45Z mloskot $");
 
 /* Hum, we cannot include gdal_priv.h from a .c file... */
 CPL_C_START
@@ -331,10 +331,13 @@ void *GDALCreateGCPRefineTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
 void GDALDestroyGCPTransformer( void *pTransformArg )
 
 {
-    GCPTransformInfo *psInfo = (GCPTransformInfo *) pTransformArg;
+    GCPTransformInfo *psInfo = NULL;
+
+    if( pTransformArg == NULL )
+        return;
+
+    psInfo = (GCPTransformInfo *) pTransformArg;
 
-    VALIDATE_POINTER0( pTransformArg, "GDALDestroyGCPTransformer" );
-    
     if( CPLAtomicDec(&(psInfo->nRefCount)) == 0 )
     {
         GDALDeinitGCPs( psInfo->nGCPCount, psInfo->pasGCPList );
diff --git a/alg/gdal_rpc.cpp b/alg/gdal_rpc.cpp
index b37ca37..812e5e2 100644
--- a/alg/gdal_rpc.cpp
+++ b/alg/gdal_rpc.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rpc.cpp 29123 2015-05-03 11:05:46Z bishop $
+ * $Id: gdal_rpc.cpp 29207 2015-05-18 17:23:45Z mloskot $
  *
  * Project:  Image Warper
  * Purpose:  Implements a rational polynomail (RPC) based transformer. 
@@ -34,7 +34,7 @@
 #include "cpl_minixml.h"
 #include "gdal_mdreader.h"
 
-CPL_CVSID("$Id: gdal_rpc.cpp 29123 2015-05-03 11:05:46Z bishop $");
+CPL_CVSID("$Id: gdal_rpc.cpp 29207 2015-05-18 17:23:45Z mloskot $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg );
@@ -259,8 +259,8 @@ typedef struct {
 
     OGRCoordinateTransformation *poCT;
 
-    double      adfGeoTransform[6];
-    double      adfReverseGeoTransform[6];
+    double      adfDEMGeoTransform[6];
+    double      adfDEMReverseGeoTransform[6];
 } GDALRPCTransformInfo;
 
 /************************************************************************/
@@ -357,7 +357,7 @@ void* GDALCreateSimilarRPCTransformer( void *hTransformArg, double dfRatioX, dou
  * normally read from metadata using GDALExtractRPCInfo().  
  *
  * GDAL RPC Metadata has the following entries (also described in GDAL RFC 22
- * and the GeoTIFF RPC document http://geotiff.maptools.org/rpc_prop.html.  
+ * and the GeoTIFF RPC document http://geotiff.maptools.org/rpc_prop.html .  
  *
  * <ul>
  * <li>ERR_BIAS: Error - Bias. The RMS bias error in meters per horizontal axis of all points in the image (-1.0 if unknown)
@@ -570,6 +570,9 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
 void GDALDestroyRPCTransformer( void *pTransformAlg )
 
 {
+    if( pTransformAlg == NULL )
+        return;
+
     GDALRPCTransformInfo *psTransform = (GDALRPCTransformInfo *) pTransformAlg;
 
     CPLFree( psTransform->pszDEMPath );
@@ -806,6 +809,187 @@ int GDALRPCGetDEMHeight( GDALRPCTransformInfo *psTransform,
 }
 
 /************************************************************************/
+/*                    GDALRPCTransformWholeLineWithDEM()                */
+/************************************************************************/
+
+static int GDALRPCTransformWholeLineWithDEM( GDALRPCTransformInfo *psTransform, 
+                                             int nPointCount, 
+                                             double *padfX, double *padfY, double *padfZ,
+                                             int *panSuccess,
+                                             int nXLeft, int nXWidth,
+                                             int nYTop, int nYHeight )
+{
+    int i;
+    GDALRPCInfo *psRPC = &(psTransform->sRPC);
+
+    double* padfDEMBuffer = (double*) VSIMalloc2(sizeof(double), nXWidth * nYHeight);
+    if( padfDEMBuffer == NULL )
+    {
+        for( i = 0; i < nPointCount; i++ )
+            panSuccess[i] = FALSE;
+        return FALSE;
+    }
+    CPLErr eErr = psTransform->poDS->GetRasterBand(1)->
+            RasterIO(GF_Read, nXLeft, nYTop, nXWidth, nYHeight,
+                        padfDEMBuffer, nXWidth, nYHeight,
+                        GDT_Float64, 0, 0, NULL);
+    if( eErr != CE_None )
+    {
+        for( i = 0; i < nPointCount; i++ )
+            panSuccess[i] = FALSE;
+        VSIFree(padfDEMBuffer);
+        return FALSE;
+    }
+
+
+    int bGotNoDataValue = FALSE;
+    double dfNoDataValue = 0;
+    dfNoDataValue = psTransform->poDS->GetRasterBand(1)->GetNoDataValue( &bGotNoDataValue );
+
+    double dfY = psTransform->adfDEMReverseGeoTransform[3] +
+                        padfY[0] * psTransform->adfDEMReverseGeoTransform[5];
+    int nY = int(dfY);
+    double dfDeltaY = dfY - nY;
+
+    for( i = 0; i < nPointCount; i++ )
+    {
+        double dfX = psTransform->adfDEMReverseGeoTransform[0] +
+                        padfX[i] * psTransform->adfDEMReverseGeoTransform[1];
+
+        double dfDEMH(0);
+
+        int nX = int(dfX);
+        double dfDeltaX = dfX - nX;
+
+        if(psTransform->eResampleAlg == DRA_Cubic)
+        {
+            int nXNew = nX - 1;
+
+            double dfSumH(0), dfSumWeight(0);
+            for ( int k_i = 0; k_i < 4; k_i++ )
+            {
+                // Loop across the X axis
+                for ( int k_j = 0; k_j < 4; k_j++ )
+                {
+                    // Calculate the weight for the specified pixel according
+                    // to the bicubic b-spline kernel we're using for
+                    // interpolation
+                    int dKernIndX = k_j - 1;
+                    int dKernIndY = k_i - 1;
+                    double dfPixelWeight = BiCubicKernel(dKernIndX - dfDeltaX) * BiCubicKernel(dKernIndY - dfDeltaY);
+
+                    // Create a sum of all values
+                    // adjusted for the pixel's calculated weight
+                    double dfElev = padfDEMBuffer[k_i * nXWidth + nXNew - nXLeft + k_j];
+                    if( bGotNoDataValue && ARE_REAL_EQUAL(dfNoDataValue, dfElev) )
+                        continue;
+
+                    dfSumH += dfElev * dfPixelWeight;
+                    dfSumWeight += dfPixelWeight;
+                }
+            }
+            if( dfSumWeight == 0.0 )
+            {
+                if( psTransform->bHasDEMMissingValue )
+                    dfDEMH = psTransform->dfDEMMissingValue;
+                else
+                {
+                    panSuccess[i] = FALSE;
+                    continue;
+                }
+            }
+            else
+                dfDEMH = dfSumH / dfSumWeight;
+        }
+        else if(psTransform->eResampleAlg == DRA_Bilinear)
+        {
+
+            //bilinear interpolation
+            double adfElevData[4];
+            memcpy(adfElevData, padfDEMBuffer + nX - nXLeft, 2 * sizeof(double));
+            memcpy(adfElevData + 2, padfDEMBuffer + nXWidth + nX - nXLeft, 2 * sizeof(double));
+
+            int bFoundNoDataElev = FALSE;
+            if( bGotNoDataValue )
+            {
+                int k_valid_sample = -1;
+                for(int k_i=0;k_i<4;k_i++)
+                {
+                    if( ARE_REAL_EQUAL(dfNoDataValue, adfElevData[k_i]) )
+                    {
+                        bFoundNoDataElev = TRUE;
+                    }
+                    else if( k_valid_sample < 0 )
+                        k_valid_sample = k_i;
+                }
+                if( bFoundNoDataElev )
+                {
+                    if( k_valid_sample >= 0 )
+                    {
+                        dfDEMH = adfElevData[k_valid_sample];
+                        RPCTransformPoint( psRPC, padfX[i], padfY[i], 
+                            padfZ[i] + (psTransform->dfHeightOffset + dfDEMH) *
+                                        psTransform->dfHeightScale, 
+                            padfX + i, padfY + i );
+
+                        panSuccess[i] = TRUE;
+                        continue;
+                    }
+                    else if( psTransform->bHasDEMMissingValue )
+                    {
+                        dfDEMH = psTransform->dfDEMMissingValue;
+                        RPCTransformPoint( psRPC, padfX[i], padfY[i], 
+                            padfZ[i] + (psTransform->dfHeightOffset + dfDEMH) *
+                                        psTransform->dfHeightScale, 
+                            padfX + i, padfY + i );
+
+                        panSuccess[i] = TRUE;
+                        continue;
+                    }
+                    else
+                    {
+                        panSuccess[i] = FALSE;
+                        continue;
+                    }
+                }
+            }
+            double dfDeltaX1 = 1.0 - dfDeltaX;                
+            double dfDeltaY1 = 1.0 - dfDeltaY;
+
+            double dfXZ1 = adfElevData[0] * dfDeltaX1 + adfElevData[1] * dfDeltaX;
+            double dfXZ2 = adfElevData[2] * dfDeltaX1 + adfElevData[3] * dfDeltaX;
+            double dfYZ = dfXZ1 * dfDeltaY1 + dfXZ2 * dfDeltaY;
+            dfDEMH = dfYZ;
+        }
+        else
+        {
+            dfDEMH = padfDEMBuffer[nX - nXLeft];
+            if( bGotNoDataValue && ARE_REAL_EQUAL(dfNoDataValue, dfDEMH) )
+            {
+                if( psTransform->bHasDEMMissingValue )
+                    dfDEMH = psTransform->dfDEMMissingValue;
+                else
+                {
+                    panSuccess[i] = FALSE;
+                    continue;
+                }
+            }
+        }
+
+        RPCTransformPoint( psRPC, padfX[i], padfY[i], 
+                            padfZ[i] + (psTransform->dfHeightOffset + dfDEMH) *
+                                        psTransform->dfHeightScale, 
+                            padfX + i, padfY + i );
+
+        panSuccess[i] = TRUE;
+    }
+
+    VSIFree(padfDEMBuffer);
+    
+    return TRUE;
+}
+
+/************************************************************************/
 /*                          GDALRPCTransform()                          */
 /************************************************************************/
 
@@ -851,9 +1035,9 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
             }
 
             if (psTransform->poDS->GetGeoTransform(
-                                psTransform->adfGeoTransform) == CE_None &&
-                GDALInvGeoTransform( psTransform->adfGeoTransform,
-                                     psTransform->adfReverseGeoTransform ))
+                                psTransform->adfDEMGeoTransform) == CE_None &&
+                GDALInvGeoTransform( psTransform->adfDEMGeoTransform,
+                                     psTransform->adfDEMReverseGeoTransform ))
             {
                 bIsValid = TRUE;
             }
@@ -872,6 +1056,77 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
 /* -------------------------------------------------------------------- */
     if( bDstToSrc )
     {
+        /* Optimization to avoid doing too many picking in DEM in the particular */
+        /* case where each point to transform is on a single line of the DEM */
+        /* To make it simple and fast we check that all input latitudes are */
+        /* identical, that the DEM is in WGS84 geodetic and that it has no rotation. */
+        /* Such case is for example triggered when doing gdalwarp with a target SRS */
+        /* of EPSG:4326 or EPSG:3857 */
+        if( nPointCount >= 10 && psTransform->poDS != NULL &&
+            psTransform->poCT == NULL && padfY[0] == padfY[nPointCount-1] &&
+            padfY[0] == padfY[nPointCount/ 2] && 
+            psTransform->adfDEMReverseGeoTransform[1] > 0.0 &&
+            psTransform->adfDEMReverseGeoTransform[2] == 0.0 && 
+            psTransform->adfDEMReverseGeoTransform[4] == 0.0 &&
+            CSLTestBoolean(CPLGetConfigOption("GDAL_RPC_DEM_OPTIM", "YES")) )
+        {
+            int bUseOptimized = TRUE;
+            double dfMinX = padfX[0], dfMaxX = padfX[0];
+            for(i = 1; i < nPointCount; i++)
+            {
+                if( padfY[i] != padfY[0] )
+                {
+                    bUseOptimized = FALSE;
+                    break;
+                }
+                if( padfX[i] < dfMinX ) dfMinX = padfX[i];
+                if( padfX[i] > dfMaxX ) dfMaxX = padfX[i];
+            }
+            if( bUseOptimized )
+            {
+                double dfX1, dfY1, dfX2, dfY2;
+                GDALApplyGeoTransform( psTransform->adfDEMReverseGeoTransform,
+                                    dfMinX, padfY[0], &dfX1, &dfY1 );
+                GDALApplyGeoTransform( psTransform->adfDEMReverseGeoTransform,
+                                    dfMaxX, padfY[0], &dfX2, &dfY2 );
+
+                int nXLeft = int(floor(dfX1));
+                int nXRight = int(floor(dfX2));
+                int nXWidth = nXRight - nXLeft + 1;
+                int nYTop = int(floor(dfY1));
+                int nYHeight;
+                if( psTransform->eResampleAlg == DRA_Cubic )
+                {
+                    nXLeft --;
+                    nXWidth += 3;
+                    nYTop --;
+                    nYHeight = 4;
+                }
+                else if( psTransform->eResampleAlg == DRA_Bilinear )
+                {
+                    nXWidth ++;
+                    nYHeight = 2;
+                }
+                else
+                    nYHeight = 1;
+                if( nXLeft >= 0 && nXLeft + nXWidth <= psTransform->poDS->GetRasterXSize() &&
+                    nYTop >= 0 && nYTop + nYHeight <= psTransform->poDS->GetRasterYSize() )
+                {
+                    static int bOnce = FALSE;
+                    if( !bOnce )
+                    {
+                        bOnce = TRUE;
+                        CPLDebug("RPC", "Using GDALRPCTransformWholeLineWithDEM");
+                    }
+                    return GDALRPCTransformWholeLineWithDEM( psTransform, nPointCount, 
+                                                             padfX, padfY, padfZ,
+                                                             panSuccess,
+                                                             nXLeft, nXWidth,
+                                                             nYTop, nYHeight );
+                }
+            }
+        }
+        
         for( i = 0; i < nPointCount; i++ )
         {
             if(psTransform->poDS)
@@ -889,11 +1144,11 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
                         panSuccess[i] = FALSE;
                         continue;
                     }
-                    GDALApplyGeoTransform( psTransform->adfReverseGeoTransform,
+                    GDALApplyGeoTransform( psTransform->adfDEMReverseGeoTransform,
                                            dfXOrig, dfYOrig, &dfX, &dfY );
                 }
                 else
-                    GDALApplyGeoTransform( psTransform->adfReverseGeoTransform,
+                    GDALApplyGeoTransform( psTransform->adfDEMReverseGeoTransform,
                                            padfX[i], padfY[i], &dfX, &dfY );
 
                 double dfDEMH(0);
@@ -952,7 +1207,7 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
                 }
             }
 
-            GDALApplyGeoTransform( psTransform->adfReverseGeoTransform,
+            GDALApplyGeoTransform( psTransform->adfDEMReverseGeoTransform,
                                     dfResultX, dfResultY, &dfX, &dfY );
 
             double dfDEMH(0);
diff --git a/alg/gdal_tps.cpp b/alg/gdal_tps.cpp
index 10c4116..a7274aa 100644
--- a/alg/gdal_tps.cpp
+++ b/alg/gdal_tps.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_tps.cpp 28459 2015-02-12 13:48:21Z rouault $
+ * $Id: gdal_tps.cpp 29207 2015-05-18 17:23:45Z mloskot $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Thin Plate Spline transformer (GDAL wrapper portion)
@@ -37,7 +37,7 @@
 #include "cpl_atomic_ops.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdal_tps.cpp 28459 2015-02-12 13:48:21Z rouault $");
+CPL_CVSID("$Id: gdal_tps.cpp 29207 2015-05-18 17:23:45Z mloskot $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeTPSTransformer( void *pTransformArg );
@@ -248,7 +248,8 @@ void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList,
 void GDALDestroyTPSTransformer( void *pTransformArg )
 
 {
-    VALIDATE_POINTER0( pTransformArg, "GDALDestroyTPSTransformer" );
+    if( pTransformArg == NULL )
+        return;
 
     TPSTransformInfo *psInfo = (TPSTransformInfo *) pTransformArg;
 
diff --git a/alg/gdalgeoloc.cpp b/alg/gdalgeoloc.cpp
index e701da4..b17f526 100644
--- a/alg/gdalgeoloc.cpp
+++ b/alg/gdalgeoloc.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgeoloc.cpp 27942 2014-11-11 00:57:41Z rouault $
+ * $Id: gdalgeoloc.cpp 29207 2015-05-18 17:23:45Z mloskot $
  *
  * Project:  GDAL
  * Purpose:  Implements Geolocation array based transformer.
@@ -38,7 +38,7 @@ SHPHandle hSHP = NULL;
 DBFHandle hDBF = NULL;
 #endif
 
-CPL_CVSID("$Id: gdalgeoloc.cpp 27942 2014-11-11 00:57:41Z rouault $");
+CPL_CVSID("$Id: gdalgeoloc.cpp 29207 2015-05-18 17:23:45Z mloskot $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg );
@@ -913,6 +913,9 @@ void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
 void GDALDestroyGeoLocTransformer( void *pTransformAlg )
 
 {
+    if( pTransformAlg == NULL )
+        return;
+
     GDALGeoLocTransformInfo *psTransform = 
         (GDALGeoLocTransformInfo *) pTransformAlg;
 
diff --git a/alg/gdaltransformer.cpp b/alg/gdaltransformer.cpp
index ee2b659..d692b9c 100644
--- a/alg/gdaltransformer.cpp
+++ b/alg/gdaltransformer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaltransformer.cpp 28916 2015-04-16 14:13:13Z rouault $
+ * $Id: gdaltransformer.cpp 29207 2015-05-18 17:23:45Z mloskot $
  *
  * 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 28916 2015-04-16 14:13:13Z rouault $");
+CPL_CVSID("$Id: gdaltransformer.cpp 29207 2015-05-18 17:23:45Z mloskot $");
 CPL_C_START
 void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree );
 void *GDALDeserializeTPSTransformer( CPLXMLNode *psTree );
@@ -1152,6 +1152,7 @@ static GDALGenImgProjTransformInfo* GDALCreateGenImgProjTransformerInternal()
  * to georef transformation on the destination dataset.
  * <li> RPC_HEIGHT: A fixed height to be used with RPC calculations.
  * <li> RPC_DEM: The name of a DEM file to be used with RPC calculations.
+ * <li> Other RPC related options. See GDALCreateRPCTransformer()
  * <li> INSERT_CENTER_LONG: May be set to FALSE to disable setting up a 
  * CENTER_LONG value on the coordinate system to rewrap things around the
  * center of the image.  
@@ -1676,7 +1677,8 @@ void GDALSetGenImgProjTransformerDstGeoTransform(
 void GDALDestroyGenImgProjTransformer( void *hTransformArg )
 
 {
-    VALIDATE_POINTER0( hTransformArg, "GDALDestroyGenImgProjTransformer" );
+    if( hTransformArg == NULL )
+        return;
 
     GDALGenImgProjTransformInfo *psInfo = 
         (GDALGenImgProjTransformInfo *) hTransformArg;
@@ -2364,7 +2366,8 @@ void *GDALCreateReprojectionTransformer( const char *pszSrcWKT,
 void GDALDestroyReprojectionTransformer( void *pTransformArg )
 
 {
-    VALIDATE_POINTER0( pTransformArg, "GDALDestroyReprojectionTransformer" );
+    if( pTransformArg == NULL )
+        return;
 
     GDALReprojectionTransformInfo *psInfo = 
         (GDALReprojectionTransformInfo *) pTransformArg;		
@@ -2671,7 +2674,8 @@ void GDALApproxTransformerOwnsSubtransformer( void *pCBData, int bOwnFlag )
 void GDALDestroyApproxTransformer( void * pCBData )
 
 {
-    VALIDATE_POINTER0( pCBData, "GDALDestroyApproxTransformer" );
+    if( pCBData == NULL)
+        return;
 
     ApproxTransformInfo	*psATInfo = (ApproxTransformInfo *) pCBData;
 
@@ -2911,13 +2915,29 @@ static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoint
 /*      approximation of the reverse transform.  Eventually we          */
 /*      should implement iterative searching to find a result within    */
 /*      our error threshold.                                            */
+/*      NOTE: the above comment is not true: gdalwarp uses approximator */
+/*      also to compute the source pixel of each target pixel.          */
 /* -------------------------------------------------------------------- */
     for( i = nPoints-1; i >= 0; i-- )
     {
+#ifdef check_error
+        double xtemp = x[i], ytemp = y[i], ztemp = z[i];
+        double x_ori = xtemp, y_ori = ytemp;
+        int btemp;
+        psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc,
+                                      1, &xtemp, &ytemp, &ztemp, &btemp);
+#endif
         dfDist = (x[i] - x[0]);
         x[i] = xSMETransformed[0] + dfDeltaX * dfDist;
         y[i] = ySMETransformed[0] + dfDeltaY * dfDist;
         z[i] = zSMETransformed[0] + dfDeltaZ * dfDist;
+#ifdef check_error
+        dfError = fabs(x[i] - xtemp) + fabs(y[i] - ytemp);
+        if( dfError > 4 /*10 * psATInfo->dfMaxError*/ )
+        {
+            printf("Error = %f on (%f, %f)\n", dfError,  x_ori, y_ori);
+        }
+#endif
         panSuccess[i] = TRUE;
     }
     
@@ -3333,10 +3353,13 @@ CPLErr GDALDeserializeTransformer( CPLXMLNode *psTree,
 void GDALDestroyTransformer( void *pTransformArg )
 
 {
+    if( pTransformArg == NULL )
+        return;
+
     GDALTransformerInfo *psInfo = (GDALTransformerInfo *) pTransformArg;
 
-    if( psInfo == NULL ||
-        memcmp(psInfo->abySignature,GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE)) != 0 )
+    if( memcmp(psInfo->abySignature,GDAL_GTI2_SIGNATURE,
+        strlen(GDAL_GTI2_SIGNATURE)) != 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to destroy non-GTI2 transformer." );
diff --git a/alg/gdalwarper.cpp b/alg/gdalwarper.cpp
index ecc8a94..09cfec6 100644
--- a/alg/gdalwarper.cpp
+++ b/alg/gdalwarper.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarper.cpp 28919 2015-04-16 18:57:58Z rouault $
+ * $Id: gdalwarper.cpp 29207 2015-05-18 17:23:45Z mloskot $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implementation of high level convenience APIs for warper.
@@ -34,7 +34,7 @@
 #include "ogr_api.h"
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalwarper.cpp 28919 2015-04-16 18:57:58Z rouault $");
+CPL_CVSID("$Id: gdalwarper.cpp 29207 2015-05-18 17:23:45Z mloskot $");
 
 /************************************************************************/
 /*                         GDALReprojectImage()                         */
@@ -960,7 +960,8 @@ GDALWarpOptions * CPL_STDCALL GDALCreateWarpOptions()
 void CPL_STDCALL GDALDestroyWarpOptions( GDALWarpOptions *psOptions )
 
 {
-    VALIDATE_POINTER0( psOptions, "GDALDestroyWarpOptions" );
+    if( psOptions == NULL )
+        return;
 
     CSLDestroy( psOptions->papszWarpOptions );
     CPLFree( psOptions->panSrcBands );
diff --git a/apps/GNUmakefile b/apps/GNUmakefile
index 8eb6387..2f6b749 100644
--- a/apps/GNUmakefile
+++ b/apps/GNUmakefile
@@ -4,7 +4,7 @@
 
 include ../GDALmake.opt
 
-CPPFLAGS :=	-I$(GDAL_ROOT)/frmts/vrt $(CPPFLAGS)
+CPPFLAGS :=	-I$(GDAL_ROOT)/frmts/vrt $(CPPFLAGS) $(JSON_INCLUDE) -I$(GDAL_ROOT)/ogr/ogrsf_frmts/geojson
 LNK_FLAGS :=	$(LDFLAGS)
 DEP_LIBS =	$(EXE_DEP_LIBS) $(XTRAOBJ)
 
diff --git a/apps/gdal_utilities.dox b/apps/gdal_utilities.dox
index d866b02..8d7019d 100644
--- a/apps/gdal_utilities.dox
+++ b/apps/gdal_utilities.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: gdal_utilities.dox 29105 2015-05-02 10:13:13Z rouault $ */
+/* $Id: gdal_utilities.dox 29243 2015-05-24 15:53:26Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
 /*! 
@@ -173,7 +173,7 @@ and exit.
 
 \htmlonly
 <p>
-$Id: gdal_utilities.dox 29105 2015-05-02 10:13:13Z rouault $
+$Id: gdal_utilities.dox 29243 2015-05-24 15:53:26Z rouault $
 </p>
 \endhtmlonly
 */
@@ -186,7 +186,7 @@ lists information about a raster dataset
 \section gdalinfo_synopsis SYNOPSIS
 
 \verbatim
-gdalinfo [--help-general] [-mm] [-stats] [-hist] [-nogcp] [-nomd]
+gdalinfo [--help-general] [-json] [-mm] [-stats] [-hist] [-nogcp] [-nomd]
          [-norat] [-noct] [-nofl] [-checksum] [-proj4]
          [-listmdd] [-mdd domain|`all`]*
          [-sd subdataset] [-oo NAME=VALUE]* datasetname
@@ -197,6 +197,7 @@ gdalinfo [--help-general] [-mm] [-stats] [-hist] [-nogcp] [-nomd]
 The gdalinfo program lists various information about a GDAL supported
 raster dataset. 
 <dl>
+<dt> <b>-json</b></dt><dd> Display the output in json format.</dd>
 <dt> <b>-mm</b></dt><dd> Force computation of the actual min/max values for each
 band in the dataset.</dd>
 <dt> <b>-stats</b></dt><dd> Read and display image statistics. Force computation if no statistics are stored in an image.</dd>
diff --git a/apps/gdalinfo.c b/apps/gdalinfo.c
index b02b911..837989d 100644
--- a/apps/gdalinfo.c
+++ b/apps/gdalinfo.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalinfo.c 28899 2015-04-14 09:27:00Z rouault $
+ * $Id: gdalinfo.c 29243 2015-05-24 15:53:26Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Commandline application to list info about a file.
@@ -35,21 +35,29 @@
 #include "cpl_conv.h"
 #include "cpl_multiproc.h"
 #include "commonutils.h"
+#include "json.h"
+#include "ogrgeojsonwriter.h"
 
-CPL_CVSID("$Id: gdalinfo.c 28899 2015-04-14 09:27:00Z rouault $");
+CPL_CVSID("$Id: gdalinfo.c 29243 2015-05-24 15:53:26Z rouault $");
 
 static int 
 GDALInfoReportCorner( GDALDatasetH hDataset, 
-                      OGRCoordinateTransformationH hTransform,
+                      OGRCoordinateTransformationH hTransform, OGRCoordinateTransformationH hTransformWGS84,
                       const char * corner_name,
-                      double x, double y );
+                      double x, double y,
+                      int bJson, json_object *poCornerCoordinates,
+                      json_object *poWGS84ExtentCoordinates );
 
 static void
 GDALInfoReportMetadata( GDALMajorObjectH hObject,
                         int bListMDD,
                         int bShowMetadata,
                         char **papszExtraMDDomains,
-                        int bIsBand );
+                        int bIsBand,
+                        int bJson,
+                        json_object *poMetadata );
+
+
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -58,7 +66,7 @@ GDALInfoReportMetadata( GDALMajorObjectH hObject,
 void Usage(const char* pszErrorMsg)
 
 {
-    printf( "Usage: gdalinfo [--help-general] [-mm] [-stats] [-hist] [-nogcp] [-nomd]\n"
+    printf( "Usage: gdalinfo [--help-general] [-json] [-mm] [-stats] [-hist] [-nogcp] [-nomd]\n"
             "                [-norat] [-noct] [-nofl] [-checksum] [-proj4]\n"
             "                [-listmdd] [-mdd domain|`all`]*\n"
             "                [-sd subdataset] [-oo NAME=VALUE]* datasetname\n" );
@@ -80,11 +88,11 @@ void Usage(const char* pszErrorMsg)
 int main( int argc, char ** argv ) 
 
 {
-    GDALDatasetH	hDataset = NULL;
-    GDALRasterBandH	hBand = NULL;
-    int			i, iBand;
-    double		adfGeoTransform[6];
-    GDALDriverH		hDriver;
+    GDALDatasetH    hDataset = NULL;
+    GDALRasterBandH hBand = NULL;
+    int         i, iBand;
+    double      adfGeoTransform[6];
+    GDALDriverH     hDriver;
     int                 bComputeMinMax = FALSE, bSample = FALSE;
     int                 bShowGCPs = TRUE, bShowMetadata = TRUE, bShowRAT=TRUE;
     int                 bStats = FALSE, bApproxStats = TRUE;
@@ -96,10 +104,13 @@ int main( int argc, char ** argv )
     char              **papszExtraMDDomains = NULL, **papszFileList;
     int                 bListMDD = FALSE;
     const char  *pszProjection = NULL;
-    OGRCoordinateTransformationH hTransform = NULL;
+    OGRCoordinateTransformationH hTransform = NULL, hTransformWGS84 = NULL;
     int             bShowFileList = TRUE;
     char              **papszOpenOptions = NULL;
 
+    int bJson = FALSE;
+    json_object *poJsonObject = NULL, *poBands = NULL, *poMetadata = NULL;
+
     /* Check that we are running against at least GDAL 1.5 */
     /* Note to developers : if we use newer API, please change the requirement */
     if (atoi(GDALVersionInfo("VERSION_NUM")) < 1500)
@@ -130,6 +141,8 @@ int main( int argc, char ** argv )
         }
         else if( EQUAL(argv[i],"--help") )
             Usage(NULL);
+        else if( EQUAL(argv[i],"-json") )
+            bJson = TRUE;
         else if( EQUAL(argv[i], "-mm") )
             bComputeMinMax = TRUE;
         else if( EQUAL(argv[i], "-hist") )
@@ -274,28 +287,80 @@ int main( int argc, char ** argv )
 /*      Report general info.                                            */
 /* -------------------------------------------------------------------- */
     hDriver = GDALGetDatasetDriver( hDataset );
-    printf( "Driver: %s/%s\n",
-            GDALGetDriverShortName( hDriver ),
-            GDALGetDriverLongName( hDriver ) );
+    if(bJson)
+    {
+        json_object *poDescription = json_object_new_string(GDALGetDescription(hDataset));
+        json_object *poDriverShortName = json_object_new_string(GDALGetDriverShortName(hDriver));
+        json_object *poDriverLongName = json_object_new_string(GDALGetDriverLongName(hDriver));
+        poJsonObject = json_object_new_object();
+        poBands = json_object_new_array();
+        poMetadata = json_object_new_object();
+
+        json_object_object_add(poJsonObject, "description", poDescription);
+        json_object_object_add(poJsonObject, "driverShortName", poDriverShortName);
+        json_object_object_add(poJsonObject, "driverLongName", poDriverLongName);
+    }
+    else
+    {
+        printf( "Driver: %s/%s\n",
+                GDALGetDriverShortName( hDriver ),
+                GDALGetDriverLongName( hDriver ) );
+
+    }
 
     papszFileList = GDALGetFileList( hDataset );
+
     if( CSLCount(papszFileList) == 0 )
-    {
-        printf( "Files: none associated\n" );
+    {   
+        if(bJson)
+        {
+            json_object *poFiles = json_object_new_array();   
+            json_object_object_add(poJsonObject, "files", poFiles);
+        }
+        else
+            printf( "Files: none associated\n" );
     }
     else
     {
-        printf( "Files: %s\n", papszFileList[0] );
-        if( bShowFileList )
+        if(bJson)
+        {
+            json_object *poFiles = json_object_new_array();
+
+            for(i = 0; papszFileList[i] != NULL; i++)
+            {
+                json_object *poFile = json_object_new_string(papszFileList[i]);
+                
+                json_object_array_add(poFiles, poFile);
+            }
+            
+            json_object_object_add(poJsonObject, "files", poFiles);
+        }
+        else
         {
-            for( i = 1; papszFileList[i] != NULL; i++ )
-                printf( "       %s\n", papszFileList[i] );
+            printf( "Files: %s\n", papszFileList[0] );
+            if( bShowFileList )
+            {
+                for( i = 1; papszFileList[i] != NULL; i++ )
+                    printf( "       %s\n", papszFileList[i] );
+            }
         }
+
     }
     CSLDestroy( papszFileList );
 
-    printf( "Size is %d, %d\n",
-            GDALGetRasterXSize( hDataset ), 
+    if(bJson)
+    {
+        json_object *poSize = json_object_new_array();
+        json_object *poSizeX = json_object_new_int(GDALGetRasterXSize(hDataset));
+        json_object *poSizeY = json_object_new_int(GDALGetRasterYSize(hDataset));
+        
+        json_object_array_add(poSize, poSizeX);
+        json_object_array_add(poSize, poSizeY);
+        json_object_object_add(poJsonObject, "size", poSize);
+    }
+    else
+        printf( "Size is %d, %d\n",
+            GDALGetRasterXSize( hDataset ),
             GDALGetRasterYSize( hDataset ) );
 
 /* -------------------------------------------------------------------- */
@@ -304,31 +369,61 @@ int main( int argc, char ** argv )
     if( GDALGetProjectionRef( hDataset ) != NULL )
     {
         OGRSpatialReferenceH  hSRS;
-        char		      *pszProjection;
+        char              *pszProjection;
+        json_object *poCoordinateSystem = NULL;
+
+        if(bJson)
+            poCoordinateSystem = json_object_new_object();
 
         pszProjection = (char *) GDALGetProjectionRef( hDataset );
 
         hSRS = OSRNewSpatialReference(NULL);
         if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )
         {
-            char	*pszPrettyWkt = NULL;
+            char    *pszPrettyWkt = NULL;
 
             OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );
-            printf( "Coordinate System is:\n%s\n", pszPrettyWkt );
+            
+            if(bJson)
+            {
+                json_object *poWkt = json_object_new_string(pszPrettyWkt);
+                json_object_object_add(poCoordinateSystem, "wkt", poWkt);
+            }
+            else
+                printf( "Coordinate System is:\n%s\n", pszPrettyWkt );
             CPLFree( pszPrettyWkt );
         }
         else
-            printf( "Coordinate System is `%s'\n",
+        {
+            if(bJson)
+            {
+                json_object *poWkt = json_object_new_string(GDALGetProjectionRef(hDataset));
+                json_object_object_add(poCoordinateSystem, "wkt", poWkt);
+            }
+            else
+                printf( "Coordinate System is `%s'\n",
                     GDALGetProjectionRef( hDataset ) );
 
-        if ( bReportProj4 ) 
+        }
+
+        if ( bReportProj4 )
         {
             char *pszProj4 = NULL;
             OSRExportToProj4( hSRS, &pszProj4 );
-            printf("PROJ.4 string is:\n\'%s\'\n",pszProj4);
-            CPLFree( pszProj4 ); 
+            
+            if(bJson)
+            {
+                json_object *proj4 = json_object_new_string(pszProj4);
+                json_object_object_add(poCoordinateSystem, "proj4", proj4);
+            }
+            else
+                printf("PROJ.4 string is:\n\'%s\'\n",pszProj4);
+            CPLFree( pszProj4 );
         }
 
+        if(bJson)
+            json_object_object_add(poJsonObject, "coordinateSystem", poCoordinateSystem);
+
         OSRDestroySpatialReference( hSRS );
     }
 
@@ -337,24 +432,40 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
     if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
     {
-        if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 )
+        if(bJson)
         {
-            CPLprintf( "Origin = (%.15f,%.15f)\n",
-                    adfGeoTransform[0], adfGeoTransform[3] );
+            json_object *poGeoTransform = json_object_new_array();
+            
+            for(i = 0; i < 6; i++)
+            {
+                json_object *poGeoTransformCoefficient = json_object_new_double_with_precision(adfGeoTransform[i], 16);
+                json_object_array_add(poGeoTransform, poGeoTransformCoefficient);
+            }
 
-            CPLprintf( "Pixel Size = (%.15f,%.15f)\n",
-                    adfGeoTransform[1], adfGeoTransform[5] );
+            json_object_object_add(poJsonObject, "geoTransform", poGeoTransform);
         }
         else
-            CPLprintf( "GeoTransform =\n"
-                    "  %.16g, %.16g, %.16g\n"
-                    "  %.16g, %.16g, %.16g\n", 
-                    adfGeoTransform[0],
-                    adfGeoTransform[1],
-                    adfGeoTransform[2],
-                    adfGeoTransform[3],
-                    adfGeoTransform[4],
-                    adfGeoTransform[5] );
+        {
+            if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 )
+            {
+                CPLprintf( "Origin = (%.15f,%.15f)\n",
+                        adfGeoTransform[0], adfGeoTransform[3] );
+
+                CPLprintf( "Pixel Size = (%.15f,%.15f)\n",
+                        adfGeoTransform[1], adfGeoTransform[5] );
+            }
+            else
+                CPLprintf( "GeoTransform =\n"
+                        "  %.16g, %.16g, %.16g\n"
+                        "  %.16g, %.16g, %.16g\n",
+                        adfGeoTransform[0],
+                        adfGeoTransform[1],
+                        adfGeoTransform[2],
+                        adfGeoTransform[3],
+                        adfGeoTransform[4],
+                        adfGeoTransform[5] );
+        }
+
     }
 
 /* -------------------------------------------------------------------- */
@@ -362,49 +473,105 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
     if( bShowGCPs && GDALGetGCPCount( hDataset ) > 0 )
     {
+        json_object *poGCPs = NULL, *poGCPList = NULL;
+
+        if(bJson)
+            poGCPs = json_object_new_object();
+        
         if (GDALGetGCPProjection(hDataset) != NULL)
         {
+            json_object *poGCPCoordinateSystem = NULL;
             OGRSpatialReferenceH  hSRS;
-            char		      *pszProjection;
+            char              *pszProjection;
 
             pszProjection = (char *) GDALGetGCPProjection( hDataset );
 
             hSRS = OSRNewSpatialReference(NULL);
             if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )
             {
-                char	*pszPrettyWkt = NULL;
+                char    *pszPrettyWkt = NULL;
 
                 OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );
-                printf( "GCP Projection = \n%s\n", pszPrettyWkt );
+                if(bJson)
+                {
+                    json_object *poWkt = json_object_new_string(pszPrettyWkt);
+                    poGCPCoordinateSystem = json_object_new_object();
+                    
+                    json_object_object_add(poGCPCoordinateSystem, "wkt", poWkt);
+                }
+                else
+                    printf( "GCP Projection = \n%s\n", pszPrettyWkt );
                 CPLFree( pszPrettyWkt );
             }
             else
-                printf( "GCP Projection = %s\n",
+            {
+                if(bJson)
+                {
+                    json_object *poWkt = json_object_new_string(GDALGetGCPProjection(hDataset));
+                    poGCPCoordinateSystem = json_object_new_object();
+                    
+                    json_object_object_add(poGCPCoordinateSystem, "wkt", poWkt);
+                }
+                else
+                    printf( "GCP Projection = %s\n",
                         GDALGetGCPProjection( hDataset ) );
 
+            }
+
+            if(bJson)
+                json_object_object_add(poGCPs, "coordinateSystem", poGCPCoordinateSystem);
             OSRDestroySpatialReference( hSRS );
         }
 
+        if(bJson)
+            poGCPList = json_object_new_array();
+
         for( i = 0; i < GDALGetGCPCount(hDataset); i++ )
         {
-            const GDAL_GCP	*psGCP;
-            
-            psGCP = GDALGetGCPs( hDataset ) + i;
+            const GDAL_GCP  *psGCP;
 
-            CPLprintf( "GCP[%3d]: Id=%s, Info=%s\n"
-                    "          (%.15g,%.15g) -> (%.15g,%.15g,%.15g)\n", 
-                    i, psGCP->pszId, psGCP->pszInfo, 
-                    psGCP->dfGCPPixel, psGCP->dfGCPLine, 
+            psGCP = GDALGetGCPs( hDataset ) + i;
+            if(bJson)
+            {
+                json_object *poGCP = json_object_new_object();
+                json_object *poId = json_object_new_string(psGCP->pszId);
+                json_object *poInfo = json_object_new_string(psGCP->pszInfo);
+                json_object *poPixel = json_object_new_double_with_precision(psGCP->dfGCPPixel, 15);
+                json_object *poLine = json_object_new_double_with_precision(psGCP->dfGCPLine, 15);
+                json_object *poX = json_object_new_double_with_precision(psGCP->dfGCPX, 15);
+                json_object *poY = json_object_new_double_with_precision(psGCP->dfGCPY, 15);
+                json_object *poZ = json_object_new_double_with_precision(psGCP->dfGCPZ, 15);
+                
+                json_object_object_add(poGCP, "id", poId);
+                json_object_object_add(poGCP, "info", poInfo);
+                json_object_object_add(poGCP, "pixel", poPixel);
+                json_object_object_add(poGCP, "line", poLine);
+                json_object_object_add(poGCP, "x", poX);
+                json_object_object_add(poGCP, "y", poY);
+                json_object_object_add(poGCP, "z", poZ);
+                json_object_array_add(poGCPList, poGCP);
+            }
+            else
+                CPLprintf( "GCP[%3d]: Id=%s, Info=%s\n"
+                    "          (%.15g,%.15g) -> (%.15g,%.15g,%.15g)\n",
+                    i, psGCP->pszId, psGCP->pszInfo,
+                    psGCP->dfGCPPixel, psGCP->dfGCPLine,
                     psGCP->dfGCPX, psGCP->dfGCPY, psGCP->dfGCPZ );
         }
+        if(bJson)
+        {
+            json_object_object_add(poGCPs, "gcpList", poGCPList);
+            json_object_object_add(poJsonObject, "gcps", poGCPs);
+        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Report metadata.                                                */
 /* -------------------------------------------------------------------- */
 
-    GDALInfoReportMetadata( hDataset, bListMDD, bShowMetadata, papszExtraMDDomains, FALSE);
-
+    GDALInfoReportMetadata( hDataset, bListMDD, bShowMetadata, papszExtraMDDomains, FALSE, bJson, poMetadata );
+    if(bJson && bShowMetadata)
+        json_object_object_add( poJsonObject, "metadata", poMetadata );
 
 /* -------------------------------------------------------------------- */
 /*      Setup projected to lat/long transform if appropriate.           */
@@ -414,12 +581,20 @@ int main( int argc, char ** argv )
 
     if( pszProjection != NULL && strlen(pszProjection) > 0 )
     {
-        OGRSpatialReferenceH hProj, hLatLong = NULL;
+        OGRSpatialReferenceH hProj, hLatLong = NULL, hLatLongWGS84 = NULL;
 
         hProj = OSRNewSpatialReference( pszProjection );
         if( hProj != NULL )
+        {
             hLatLong = OSRCloneGeogCS( hProj );
 
+            if(bJson)
+            {
+                hLatLongWGS84 = OSRNewSpatialReference( NULL );
+                OSRSetWellKnownGeogCS( hLatLongWGS84, "WGS84" );
+            }
+        }
+
         if( hLatLong != NULL )
         {
             CPLPushErrorHandler( CPLQuietErrorHandler );
@@ -429,6 +604,15 @@ int main( int argc, char ** argv )
             OSRDestroySpatialReference( hLatLong );
         }
 
+        if( hLatLongWGS84 != NULL )
+        {
+            CPLPushErrorHandler( CPLQuietErrorHandler );
+            hTransformWGS84 = OCTNewCoordinateTransformation( hProj, hLatLongWGS84 );
+            CPLPopErrorHandler();
+            
+            OSRDestroySpatialReference( hLatLongWGS84 );
+        }
+
         if( hProj != NULL )
             OSRDestroySpatialReference( hProj );
     }
@@ -436,26 +620,65 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Report corners.                                                 */
 /* -------------------------------------------------------------------- */
-    printf( "Corner Coordinates:\n" );
-    GDALInfoReportCorner( hDataset, hTransform, "Upper Left", 
-                          0.0, 0.0 );
-    GDALInfoReportCorner( hDataset, hTransform, "Lower Left", 
-                          0.0, GDALGetRasterYSize(hDataset));
-    GDALInfoReportCorner( hDataset, hTransform, "Upper Right", 
-                          GDALGetRasterXSize(hDataset), 0.0 );
-    GDALInfoReportCorner( hDataset, hTransform, "Lower Right", 
-                          GDALGetRasterXSize(hDataset), 
-                          GDALGetRasterYSize(hDataset) );
-    GDALInfoReportCorner( hDataset, hTransform, "Center", 
-                          GDALGetRasterXSize(hDataset)/2.0, 
-                          GDALGetRasterYSize(hDataset)/2.0 );
+    if(bJson)
+    {
+        json_object *poLinearRing = json_object_new_array();
+        json_object *poCornerCoordinates = json_object_new_object();
+        json_object *poWGS84Extent = json_object_new_object();
+        json_object *poWGS84ExtentType = json_object_new_string("Polygon");
+        json_object *poWGS84ExtentCoordinates = json_object_new_array();
+
+        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "upperLeft",
+                              0.0, 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates );
+        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "lowerLeft",
+                              0.0, GDALGetRasterYSize(hDataset), bJson, poCornerCoordinates, poWGS84ExtentCoordinates );
+        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "upperRight",
+                              GDALGetRasterXSize(hDataset), 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates );
+        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "lowerRight",
+                              GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset),
+                              bJson, poCornerCoordinates, poWGS84ExtentCoordinates );
+        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "center",
+                              GDALGetRasterXSize(hDataset)/2.0, GDALGetRasterYSize(hDataset)/2.0,
+                              bJson, poCornerCoordinates, poWGS84ExtentCoordinates );
+        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "upperLeft",
+                              0.0, 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates );
+        
+        json_object_object_add( poJsonObject, "cornerCoordinates", poCornerCoordinates );
+        json_object_object_add( poWGS84Extent, "type", poWGS84ExtentType );
+        json_object_array_add( poLinearRing, poWGS84ExtentCoordinates );
+        json_object_object_add( poWGS84Extent, "coordinates", poLinearRing );
+        json_object_object_add( poJsonObject, "wgs84Extent", poWGS84Extent );
+    }
+    else
+    {
+        printf( "Corner Coordinates:\n" );
+        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "Upper Left",
+                              0.0, 0.0, bJson, NULL, NULL );
+        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "Lower Left",
+                              0.0, GDALGetRasterYSize(hDataset), bJson, NULL, NULL );
+        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "Upper Right",
+                              GDALGetRasterXSize(hDataset), 0.0, bJson, NULL, NULL );
+        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "Lower Right",
+                              GDALGetRasterXSize(hDataset),
+                              GDALGetRasterYSize(hDataset), bJson, NULL, NULL );
+        GDALInfoReportCorner( hDataset, hTransform, hTransformWGS84, "Center",
+                              GDALGetRasterXSize(hDataset)/2.0,
+                              GDALGetRasterYSize(hDataset)/2.0, bJson, NULL, NULL );
+
+    }
 
     if( hTransform != NULL )
     {
         OCTDestroyCoordinateTransformation( hTransform );
         hTransform = NULL;
     }
-    
+
+    if( hTransformWGS84 != NULL )
+    {
+        OCTDestroyCoordinateTransformation( hTransformWGS84 );
+        hTransformWGS84 = NULL;
+    }
+
 /* ==================================================================== */
 /*      Loop over bands.                                                */
 /* ==================================================================== */
@@ -465,8 +688,15 @@ int main( int argc, char ** argv )
         int         bGotMin, bGotMax, bGotNodata, bSuccess;
         int         nBlockXSize, nBlockYSize, nMaskFlags;
         double      dfMean, dfStdDev;
-        GDALColorTableH	hTable;
+        GDALColorTableH hTable;
         CPLErr      eErr;
+        json_object *poBand = NULL, *poBandMetadata = NULL;
+
+        if(bJson)
+        {
+            poBand = json_object_new_object();
+            poBandMetadata = json_object_new_object();
+        }
 
         hBand = GDALGetRasterBand( hDataset, iBand+1 );
 
@@ -476,11 +706,28 @@ int main( int argc, char ** argv )
             int   nCount;
 
             nCount = GDALGetRandomRasterSample( hBand, 10000, afSample );
-            printf( "Got %d samples.\n", nCount );
+            if(!bJson)
+                printf( "Got %d samples.\n", nCount );
         }
         
         GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
-        printf( "Band %d Block=%dx%d Type=%s, ColorInterp=%s\n", iBand+1,
+        if(bJson)
+        {
+            json_object *poBandNumber = json_object_new_int(iBand+1);
+            json_object *poBlock = json_object_new_array();
+            json_object *poType = json_object_new_string(GDALGetDataTypeName(GDALGetRasterDataType(hBand)));
+            json_object *poColorInterp = json_object_new_string(GDALGetColorInterpretationName(
+                GDALGetRasterColorInterpretation(hBand)));
+
+            json_object_array_add(poBlock, json_object_new_int(nBlockXSize));
+            json_object_array_add(poBlock, json_object_new_int(nBlockYSize));
+            json_object_object_add(poBand, "band", poBandNumber);
+            json_object_object_add(poBand, "block", poBlock);
+            json_object_object_add(poBand, "type", poType);
+            json_object_object_add(poBand, "colorInterpretation", poColorInterp);
+        }
+        else
+            printf( "Band %d Block=%dx%d Type=%s, ColorInterp=%s\n", iBand+1,
                 nBlockXSize, nBlockYSize,
                 GDALGetDataTypeName(
                     GDALGetRasterDataType(hBand)),
@@ -489,37 +736,83 @@ int main( int argc, char ** argv )
 
         if( GDALGetDescription( hBand ) != NULL 
             && strlen(GDALGetDescription( hBand )) > 0 )
-            printf( "  Description = %s\n", GDALGetDescription(hBand) );
+        {
+            if(bJson)
+            {
+                json_object *poBandDescription = json_object_new_string(GDALGetDescription(hBand));
+                json_object_object_add(poBand, "description", poBandDescription);
+            }
+            else
+                printf( "  Description = %s\n", GDALGetDescription(hBand) );
+        }
 
         dfMin = GDALGetRasterMinimum( hBand, &bGotMin );
         dfMax = GDALGetRasterMaximum( hBand, &bGotMax );
         if( bGotMin || bGotMax || bComputeMinMax )
         {
-            printf( "  " );
+            if(!bJson)
+                printf( "  " );
             if( bGotMin )
-                CPLprintf( "Min=%.3f ", dfMin );
+            {
+                if(bJson)
+                {
+                    json_object *poMin = json_object_new_double_with_precision(dfMin, 3);
+                    json_object_object_add(poBand, "min", poMin);
+                }
+                else
+                    CPLprintf( "Min=%.3f ", dfMin );
+            }
             if( bGotMax )
-                CPLprintf( "Max=%.3f ", dfMax );
-        
+            {
+                if(bJson)
+                {
+                    json_object *poMax = json_object_new_double_with_precision(dfMax, 3);
+                    json_object_object_add(poBand, "max", poMax);
+                }
+                else
+                    CPLprintf( "Max=%.3f ", dfMax );
+            }
+
             if( bComputeMinMax )
             {
                 CPLErrorReset();
                 GDALComputeRasterMinMax( hBand, FALSE, adfCMinMax );
                 if (CPLGetLastErrorType() == CE_None)
                 {
-                  CPLprintf( "  Computed Min/Max=%.3f,%.3f", 
+                    if(bJson)
+                    {
+                        json_object *poComputedMin = json_object_new_double_with_precision(adfCMinMax[0], 3);
+                        json_object *poComputedMax = json_object_new_double_with_precision(adfCMinMax[1], 3);
+                        json_object_object_add(poBand, "computedMin", poComputedMin);
+                        json_object_object_add(poBand, "computedMax", poComputedMax);
+                    }
+                    else
+                        CPLprintf( "  Computed Min/Max=%.3f,%.3f",
                           adfCMinMax[0], adfCMinMax[1] );
                 }
             }
-
-            printf( "\n" );
+            if(!bJson)
+                printf( "\n" );
         }
 
         eErr = GDALGetRasterStatistics( hBand, bApproxStats, bStats, 
                                         &dfMin, &dfMax, &dfMean, &dfStdDev );
         if( eErr == CE_None )
         {
-            CPLprintf( "  Minimum=%.3f, Maximum=%.3f, Mean=%.3f, StdDev=%.3f\n",
+            if(bJson)
+            {
+                json_object *poMinimum = json_object_new_double_with_precision(dfMin, 3);
+                json_object *poMaximum = json_object_new_double_with_precision(dfMax, 3);
+                json_object *poMean = json_object_new_double_with_precision(dfMean, 3);
+                json_object *poStdDev = json_object_new_double_with_precision(dfStdDev, 3);
+                
+                json_object_object_add(poBand, "minimum", poMinimum);
+                json_object_object_add(poBand, "maximum", poMaximum);
+                json_object_object_add(poBand, "mean", poMean);
+                json_object_object_add(poBand, "stdDev", poStdDev);
+            }
+            else
+                CPLprintf( "  Minimum=%.3f, Maximum=%.3f, Mean=%.3f, StdDev=%.3f\n",
                     dfMin, dfMax, dfMean, dfStdDev );
         }
 
@@ -528,99 +821,193 @@ int main( int argc, char ** argv )
             int nBucketCount;
             GUIntBig *panHistogram = NULL;
 
-            eErr = GDALGetDefaultHistogramEx( hBand, &dfMin, &dfMax, 
+            if(bJson)
+                eErr = GDALGetDefaultHistogramEx( hBand, &dfMin, &dfMax, 
+                                            &nBucketCount, &panHistogram, 
+                                            TRUE, GDALDummyProgress, NULL );
+            else
+                eErr = GDALGetDefaultHistogramEx( hBand, &dfMin, &dfMax, 
                                             &nBucketCount, &panHistogram, 
                                             TRUE, GDALTermProgress, NULL );
             if( eErr == CE_None )
             {
                 int iBucket;
+                json_object *poHistogram = NULL, *poBuckets = NULL;
 
-                printf( "  %d buckets from %g to %g:\n  ",
+                if(bJson)
+                {
+                    json_object *poCount = json_object_new_int(nBucketCount);
+                    json_object *poMin = json_object_new_double(dfMin);
+                    json_object *poMax = json_object_new_double(dfMax);
+                    
+                    poBuckets = json_object_new_array();
+                    poHistogram = json_object_new_object();
+                    json_object_object_add(poHistogram, "count", poCount);
+                    json_object_object_add(poHistogram, "min", poMin);
+                    json_object_object_add(poHistogram, "max", poMax);
+                }
+                else
+                    printf( "  %d buckets from %g to %g:\n  ",
                         nBucketCount, dfMin, dfMax );
+
                 for( iBucket = 0; iBucket < nBucketCount; iBucket++ )
-                    printf( CPL_FRMT_GUIB " ", panHistogram[iBucket] );
-                printf( "\n" );
+                {
+                    if(bJson)
+                    {
+                        json_object *poBucket = json_object_new_int64(panHistogram[iBucket]);
+                        json_object_array_add(poBuckets, poBucket);
+                    }
+                    else
+                        printf( CPL_FRMT_GUIB " ", panHistogram[iBucket] );
+                }
+                if(bJson)
+                {
+                    json_object_object_add(poHistogram, "buckets", poBuckets);
+                    json_object_object_add(poBand, "histogram", poHistogram);
+                }
+                else
+                    printf( "\n" );
                 CPLFree( panHistogram );
             }
         }
 
         if ( bComputeChecksum)
         {
-            printf( "  Checksum=%d\n",
-                    GDALChecksumImage(hBand, 0, 0,
+            int nBandChecksum = GDALChecksumImage(hBand, 0, 0,
                                       GDALGetRasterXSize(hDataset),
-                                      GDALGetRasterYSize(hDataset)));
+                                      GDALGetRasterYSize(hDataset));
+            if(bJson)
+            {
+                json_object *poChecksum = json_object_new_int(nBandChecksum);
+                json_object_object_add(poBand, "checksum", poChecksum);
+            }
+            else
+                printf( "  Checksum=%d\n", nBandChecksum );
         }
 
         dfNoData = GDALGetRasterNoDataValue( hBand, &bGotNodata );
         if( bGotNodata )
         {
             if (CPLIsNan(dfNoData))
-                printf( "  NoData Value=nan\n" );
+            {
+                if(bJson)
+                {
+                    json_object *poNoDataValue = json_object_new_string("nan");
+                    json_object_object_add(poBand, "noDataValue", poNoDataValue);
+                }
+                else
+                    printf( "  NoData Value=nan\n" );
+            }
             else
-                CPLprintf( "  NoData Value=%.18g\n", dfNoData );
+            {
+                if(bJson)
+                {
+                    json_object *poNoDataValue = json_object_new_double_with_precision(dfNoData, 18);
+                    json_object_object_add(poBand, "noDataValue", poNoDataValue);
+                }
+                else
+                    CPLprintf( "  NoData Value=%.18g\n", dfNoData );
+            }
         }
 
         if( GDALGetOverviewCount(hBand) > 0 )
         {
-            int		iOverview;
+            int     iOverview;
+            json_object *poOverviews = NULL;
+            
+            if(bJson)
+                poOverviews = json_object_new_array();
+            else
+                printf( "  Overviews: " );
 
-            printf( "  Overviews: " );
             for( iOverview = 0; 
                  iOverview < GDALGetOverviewCount(hBand);
                  iOverview++ )
             {
-                GDALRasterBandH	hOverview;
+                GDALRasterBandH hOverview;
                 const char *pszResampling = NULL;
+                json_object *poOverview;
 
-                if( iOverview != 0 )
-                    printf( ", " );
+                if(!bJson)
+                    if( iOverview != 0 )
+                        printf( ", " );
 
                 hOverview = GDALGetOverview( hBand, iOverview );
                 if (hOverview != NULL)
                 {
-                    printf( "%dx%d", 
+                    if(bJson)
+                    {
+                        json_object *poOverviewSize = json_object_new_array();
+                        json_object *poOverviewSizeX = json_object_new_int( GDALGetRasterBandXSize( hOverview) );
+                        json_object *poOverviewSizeY = json_object_new_int( GDALGetRasterBandYSize( hOverview) );
+                        
+                        poOverview = json_object_new_object();
+                        json_object_array_add( poOverviewSize, poOverviewSizeX );
+                        json_object_array_add( poOverviewSize, poOverviewSizeY );
+                        json_object_object_add( poOverview, "size", poOverviewSize );
+
+                        if(bComputeChecksum)
+                        {
+                            int nOverviewChecksum = GDALChecksumImage(hOverview, 0, 0,
+                                        GDALGetRasterBandXSize(hOverview),
+                                        GDALGetRasterBandYSize(hOverview));
+                            json_object *poOverviewChecksum = json_object_new_int(nOverviewChecksum);
+                            json_object_object_add(poOverview, "checksum", poOverviewChecksum);
+                        }
+                        json_object_array_add(poOverviews, poOverview);
+                    }
+                    else
+                        printf( "%dx%d", 
                             GDALGetRasterBandXSize( hOverview ),
                             GDALGetRasterBandYSize( hOverview ) );
 
                     pszResampling = 
                         GDALGetMetadataItem( hOverview, "RESAMPLING", "" );
 
-                    if( pszResampling != NULL 
+                    if( pszResampling != NULL && !bJson 
                         && EQUALN(pszResampling,"AVERAGE_BIT2",12) )
                         printf( "*" );
                 }
                 else
-                    printf( "(null)" );
+                    if(!bJson)
+                        printf( "(null)" );
             }
-            printf( "\n" );
+            if(bJson)
+                json_object_object_add(poBand, "overviews", poOverviews);
+            else
+                printf( "\n" );
 
-            if ( bComputeChecksum)
+            if ( bComputeChecksum && !bJson )
             {
                 printf( "  Overviews checksum: " );
+                
                 for( iOverview = 0; 
                     iOverview < GDALGetOverviewCount(hBand);
                     iOverview++ )
                 {
-                    GDALRasterBandH	hOverview;
+                    GDALRasterBandH hOverview;
 
                     if( iOverview != 0 )
                         printf( ", " );
 
                     hOverview = GDALGetOverview( hBand, iOverview );
                     if (hOverview)
+                    {
                         printf( "%d",
                                 GDALChecksumImage(hOverview, 0, 0,
                                         GDALGetRasterBandXSize(hOverview),
                                         GDALGetRasterBandYSize(hOverview)));
+                    }
                     else
+                    {
                         printf( "(null)" );
+                    }
                 }
                 printf( "\n" );
             }
         }
 
-        if( GDALHasArbitraryOverviews( hBand ) )
+        if( GDALHasArbitraryOverviews( hBand ) && !bJson )
         {
             printf( "  Overviews: arbitrary\n" );
         }
@@ -629,100 +1016,262 @@ int main( int argc, char ** argv )
         if( (nMaskFlags & (GMF_NODATA|GMF_ALL_VALID)) == 0 )
         {
             GDALRasterBandH hMaskBand = GDALGetMaskBand(hBand) ;
+            json_object *poMask = NULL, *poFlags = NULL, *poMaskOverviews = NULL;
 
-            printf( "  Mask Flags: " );
+            if(bJson)
+            {
+                poMask = json_object_new_object();
+                poFlags = json_object_new_array(); 
+            }
+            else
+                printf( "  Mask Flags: " );
             if( nMaskFlags & GMF_PER_DATASET )
-                printf( "PER_DATASET " );
+            {
+                if(bJson)
+                {
+                    json_object *poFlag = json_object_new_string( "PER_DATASET" );
+                    json_object_array_add( poFlags, poFlag );
+                }
+                else
+                    printf( "PER_DATASET " );
+            }
             if( nMaskFlags & GMF_ALPHA )
-                printf( "ALPHA " );
+            {
+                if(bJson)
+                {
+                    json_object *poFlag = json_object_new_string( "ALPHA" );
+                    json_object_array_add( poFlags, poFlag );
+                }
+                else
+                    printf( "ALPHA " );
+            }
             if( nMaskFlags & GMF_NODATA )
-                printf( "NODATA " );
+            {
+                if(bJson)
+                {
+                    json_object *poFlag = json_object_new_string( "NODATA" );
+                    json_object_array_add( poFlags, poFlag );
+                }
+                else
+                    printf( "NODATA " );
+            }
             if( nMaskFlags & GMF_ALL_VALID )
-                printf( "ALL_VALID " );
-            printf( "\n" );
+            {
+                if(bJson)
+                {
+                    json_object *poFlag = json_object_new_string( "ALL_VALID" );
+                    json_object_array_add( poFlags, poFlag );
+                }
+                else
+                    printf( "ALL_VALID " );
+            }
+            if(bJson)
+                json_object_object_add( poMask, "flags", poFlags );
+            else
+                printf( "\n" );
+
+            if(bJson)
+                poMaskOverviews = json_object_new_array();
 
             if( hMaskBand != NULL &&
                 GDALGetOverviewCount(hMaskBand) > 0 )
             {
-                int		iOverview;
-
-                printf( "  Overviews of mask band: " );
+                int     iOverview;
+                
+                if(!bJson)
+                    printf( "  Overviews of mask band: " );
+                
                 for( iOverview = 0; 
                      iOverview < GDALGetOverviewCount(hMaskBand);
                      iOverview++ )
                 {
-                    GDALRasterBandH	hOverview;
-
-                    if( iOverview != 0 )
-                        printf( ", " );
+                    GDALRasterBandH hOverview;
+                    json_object *poMaskOverviewSizeX, *poMaskOverviewSizeY,
+                                *poMaskOverview = NULL, *poMaskOverviewSize = NULL;
+
+                    if(bJson)
+                    {
+                        poMaskOverview = json_object_new_object();
+                        poMaskOverviewSize = json_object_new_array();
+                    }
+                    else
+                    {
+                        if( iOverview != 0 )
+                            printf( ", " );
+                    }
 
                     hOverview = GDALGetOverview( hMaskBand, iOverview );
-                    printf( "%dx%d", 
+                    if(bJson)
+                    {
+                        poMaskOverviewSizeX = json_object_new_int(GDALGetRasterBandXSize(hOverview));
+                        poMaskOverviewSizeY = json_object_new_int(GDALGetRasterBandYSize(hOverview));
+
+                        json_object_array_add(poMaskOverviewSize, poMaskOverviewSizeX);
+                        json_object_array_add(poMaskOverviewSize, poMaskOverviewSizeY);
+                        json_object_object_add(poMaskOverview, "size", poMaskOverviewSize);
+                        json_object_array_add(poMaskOverviews, poMaskOverview);
+                    }
+                    else
+                        printf( "%dx%d", 
                             GDALGetRasterBandXSize( hOverview ),
                             GDALGetRasterBandYSize( hOverview ) );
                 }
-                printf( "\n" );
+                if(!bJson)
+                    printf( "\n" );
             }
+            if(bJson)
+            {
+                json_object_object_add(poMask, "overviews", poMaskOverviews);
+                json_object_object_add(poBand, "mask", poMask);
+            }    
         }
 
         if( strlen(GDALGetRasterUnitType(hBand)) > 0 )
         {
-            printf( "  Unit Type: %s\n", GDALGetRasterUnitType(hBand) );
+            if(bJson)
+            {
+                json_object *poUnit = json_object_new_string(GDALGetRasterUnitType(hBand));
+                json_object_object_add(poBand, "unit", poUnit);
+            }
+            else
+                printf( "  Unit Type: %s\n", GDALGetRasterUnitType(hBand) );
         }
 
         if( GDALGetRasterCategoryNames(hBand) != NULL )
         {
             char **papszCategories = GDALGetRasterCategoryNames(hBand);
             int i;
+            json_object *poCategories = NULL;
 
-            printf( "  Categories:\n" );
+            if(bJson)
+                poCategories = json_object_new_array();           
+            else
+                printf( "  Categories:\n" );
+                
             for( i = 0; papszCategories[i] != NULL; i++ )
-                printf( "    %3d: %s\n", i, papszCategories[i] );
+            {
+                if(bJson)
+                {
+                    json_object *poCategoryName = json_object_new_string(papszCategories[i]);
+                    json_object_array_add(poCategories, poCategoryName);
+                }
+                else
+                    printf( "    %3d: %s\n", i, papszCategories[i] );
+            }
+            if(bJson)
+                json_object_object_add(poBand, "categories", poCategories);
         }
 
         if( GDALGetRasterScale( hBand, &bSuccess ) != 1.0 
             || GDALGetRasterOffset( hBand, &bSuccess ) != 0.0 )
-            CPLprintf( "  Offset: %.15g,   Scale:%.15g\n",
+        {
+            if(bJson)
+            {
+                json_object *poOffset = json_object_new_double_with_precision(GDALGetRasterOffset(hBand, &bSuccess), 15);
+                json_object *poScale = json_object_new_double_with_precision(GDALGetRasterScale(hBand, &bSuccess), 15);
+                json_object_object_add(poBand, "offset", poOffset);
+                json_object_object_add(poBand, "scale", poScale);
+            }
+            else
+                CPLprintf( "  Offset: %.15g,   Scale:%.15g\n",
                     GDALGetRasterOffset( hBand, &bSuccess ),
                     GDALGetRasterScale( hBand, &bSuccess ) );
-
-        GDALInfoReportMetadata( hBand, bListMDD, bShowMetadata, papszExtraMDDomains, TRUE);
+        }
+        
+        GDALInfoReportMetadata( hBand, bListMDD, bShowMetadata, papszExtraMDDomains, TRUE, bJson, poBandMetadata );
+        if(bJson && bShowMetadata)  
+            json_object_object_add( poBand, "metadata", poBandMetadata );
 
         if( GDALGetRasterColorInterpretation(hBand) == GCI_PaletteIndex 
             && (hTable = GDALGetRasterColorTable( hBand )) != NULL )
         {
-            int			i;
+            int         i;
+            json_object *poColorTable = NULL;
+            
+            if(bJson)
+            {
+                json_object *poPalette = json_object_new_string(GDALGetPaletteInterpretationName(
+                    GDALGetPaletteInterpretation(hTable)));
+                json_object *poCount = json_object_new_int(GDALGetColorEntryCount(hTable));
+                poColorTable = json_object_new_object();
 
-            printf( "  Color Table (%s with %d entries)\n", 
+                json_object_object_add(poColorTable, "palette", poPalette);
+                json_object_object_add(poColorTable, "count", poCount);
+            }
+            else
+                printf( "  Color Table (%s with %d entries)\n",
                     GDALGetPaletteInterpretationName(
                         GDALGetPaletteInterpretation( hTable )), 
                     GDALGetColorEntryCount( hTable ) );
 
             if (bShowColorTable)
             {
+                json_object *poEntries = NULL;
+                
+                if(bJson)
+                    poEntries = json_object_new_array();
+
                 for( i = 0; i < GDALGetColorEntryCount( hTable ); i++ )
                 {
-                    GDALColorEntry	sEntry;
+                    GDALColorEntry  sEntry;
     
                     GDALGetColorEntryAsRGB( hTable, i, &sEntry );
-                    printf( "  %3d: %d,%d,%d,%d\n", 
-                            i, 
+
+                    if(bJson)
+                    {
+                        json_object *poEntry = json_object_new_array();
+                        json_object *poC1 = json_object_new_int(sEntry.c1);
+                        json_object *poC2 = json_object_new_int(sEntry.c2);
+                        json_object *poC3 = json_object_new_int(sEntry.c3);
+                        json_object *poC4 = json_object_new_int(sEntry.c4);
+                        
+                        json_object_array_add(poEntry, poC1);
+                        json_object_array_add(poEntry, poC2);
+                        json_object_array_add(poEntry, poC3);
+                        json_object_array_add(poEntry, poC4);
+                        json_object_array_add(poEntries, poEntry);
+                    }
+                    else
+                        printf( "  %3d: %d,%d,%d,%d\n",
+                            i,
                             sEntry.c1,
                             sEntry.c2,
                             sEntry.c3,
                             sEntry.c4 );
                 }
-            }
+                if(bJson)
+                {
+                    json_object_object_add(poColorTable, "entries", poEntries);
+                    json_object_object_add(poBand, "colorTable", poColorTable);
+                }
+            }   
         }
 
         if( bShowRAT && GDALGetDefaultRAT( hBand ) != NULL )
         {
             GDALRasterAttributeTableH hRAT = GDALGetDefaultRAT( hBand );
             
-            GDALRATDumpReadable( hRAT, NULL );
+            if(bJson)
+            {
+                json_object *poRAT = (json_object*) GDALRATSerializeJSON( hRAT );
+                json_object_object_add( poJsonObject, "rat", poRAT );
+            }
+            else
+            {
+                GDALRATDumpReadable( hRAT, NULL );
+            }
         }
+        if(bJson)
+            json_object_array_add(poBands, poBand);
     }
 
+    if(bJson)
+    {
+        json_object_object_add(poJsonObject, "bands", poBands);
+        printf("%s\n", json_object_to_json_string_ext(poJsonObject, JSON_C_TO_STRING_PRETTY));
+        json_object_put(poJsonObject);
+    }
+    
     GDALClose( hDataset );
     
     CSLDestroy( papszExtraMDDomains );
@@ -745,16 +1294,19 @@ int main( int argc, char ** argv )
 
 static int 
 GDALInfoReportCorner( GDALDatasetH hDataset, 
-                      OGRCoordinateTransformationH hTransform,
+                      OGRCoordinateTransformationH hTransform, OGRCoordinateTransformationH hTransformWGS84,
                       const char * corner_name,
-                      double x, double y )
+                      double x, double y,
+                      int bJson, json_object *poCornerCoordinates, json_object *poWGS84ExtentCoordinates )
 
 {
-    double	dfGeoX, dfGeoY;
-    double	adfGeoTransform[6];
-        
-    printf( "%-11s ", corner_name );
-    
+    double  dfGeoX, dfGeoY;
+    double  adfGeoTransform[6];
+    json_object *poCorner, *poX, *poY;
+
+    if(!bJson)
+        printf( "%-11s ", corner_name );
+
 /* -------------------------------------------------------------------- */
 /*      Transform the point into georeferenced coordinates.             */
 /* -------------------------------------------------------------------- */
@@ -768,7 +1320,17 @@ GDALInfoReportCorner( GDALDatasetH hDataset,
 
     else
     {
-        CPLprintf( "(%7.1f,%7.1f)\n", x, y );
+        if( bJson )
+        {
+            poCorner = json_object_new_array();
+            poX = json_object_new_double_with_precision( x, 1 );
+            poY = json_object_new_double_with_precision( y, 1 );
+            json_object_array_add( poCorner, poX );
+            json_object_array_add( poCorner, poY );
+            json_object_object_add( poCornerCoordinates, corner_name, poCorner );
+        }
+        else
+            CPLprintf( "(%7.1f,%7.1f)\n", x, y );
         return FALSE;
     }
 
@@ -777,26 +1339,60 @@ GDALInfoReportCorner( GDALDatasetH hDataset,
 /* -------------------------------------------------------------------- */
     if( ABS(dfGeoX) < 181 && ABS(dfGeoY) < 91 )
     {
-        CPLprintf( "(%12.7f,%12.7f) ", dfGeoX, dfGeoY );
+        if(bJson)
+        {
+            poCorner = json_object_new_array();
+            poX = json_object_new_double_with_precision( dfGeoX, 7 );
+            poY = json_object_new_double_with_precision( dfGeoY, 7 );
+            json_object_array_add( poCorner, poX );
+            json_object_array_add( poCorner, poY );
+            json_object_object_add( poCornerCoordinates, corner_name, poCorner );
+        }
+        else
+            CPLprintf( "(%12.7f,%12.7f) ", dfGeoX, dfGeoY );
     }
     else
     {
-        CPLprintf( "(%12.3f,%12.3f) ", dfGeoX, dfGeoY );
+        if(bJson)
+        {
+            poCorner = json_object_new_array();
+            poX = json_object_new_double_with_precision( dfGeoX, 3 );
+            poY = json_object_new_double_with_precision( dfGeoY, 3 );
+            json_object_array_add( poCorner, poX );
+            json_object_array_add( poCorner, poY );
+            json_object_object_add( poCornerCoordinates, corner_name, poCorner );
+        }
+        else
+            CPLprintf( "(%12.3f,%12.3f) ", dfGeoX, dfGeoY );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Transform to latlong and report.                                */
 /* -------------------------------------------------------------------- */
-    if( hTransform != NULL 
-        && OCTTransform(hTransform,1,&dfGeoX,&dfGeoY,NULL) )
+    if(bJson)
     {
-        
-        printf( "(%s,", GDALDecToDMS( dfGeoX, "Long", 2 ) );
-        printf( "%s)", GDALDecToDMS( dfGeoY, "Lat", 2 ) );
+        if( hTransformWGS84 != NULL && !EQUAL( corner_name, "center" ) 
+        && OCTTransform(hTransformWGS84,1,&dfGeoX,&dfGeoY,NULL) )
+        {
+            poCorner = json_object_new_array();
+            poX = json_object_new_double_with_precision( dfGeoX, 7 );
+            poY = json_object_new_double_with_precision( dfGeoY, 7 );
+            json_object_array_add( poCorner, poX );
+            json_object_array_add( poCorner, poY );
+            json_object_array_add( poWGS84ExtentCoordinates , poCorner );
+        }
     }
-
-    printf( "\n" );
-
+    else
+    {
+        if( hTransform != NULL 
+        && OCTTransform(hTransform,1,&dfGeoX,&dfGeoY,NULL) )
+        {
+            printf( "(%s,", GDALDecToDMS( dfGeoX, "Long", 2 ) );
+            printf( "%s)", GDALDecToDMS( dfGeoY, "Lat", 2 ) );
+        }
+        printf( "\n" );
+    }
+    
     return TRUE;
 }
 
@@ -807,11 +1403,16 @@ GDALInfoReportCorner( GDALDatasetH hDataset,
 static void GDALInfoPrintMetadata( GDALMajorObjectH hObject,
                                    const char *pszDomain,
                                    const char *pszDisplayedname,
-                                   const char *pszIndent)
+                                   const char *pszIndent,
+                                   int bJson,
+                                   json_object *poMetadata )
 {
     int i;
     char **papszMetadata;
     int bIsxml = FALSE;
+    char *pszKey = NULL;
+    const char *pszValue;
+    json_object *poDomain = NULL, *poValue = NULL;
 
     if (pszDomain != NULL && EQUALN(pszDomain, "xml:", 4))
         bIsxml = TRUE;
@@ -819,15 +1420,49 @@ static void GDALInfoPrintMetadata( GDALMajorObjectH hObject,
     papszMetadata = GDALGetMetadata( hObject, pszDomain );
     if( CSLCount(papszMetadata) > 0 )
     {
-        printf( "%s%s:\n", pszIndent, pszDisplayedname );
+        if(bJson && !bIsxml)
+            poDomain = json_object_new_object();
+        
+        if(!bJson)
+            printf( "%s%s:\n", pszIndent, pszDisplayedname );
+        
         for( i = 0; papszMetadata[i] != NULL; i++ )
         {
-            if (bIsxml)
-                printf( "%s%s\n", pszIndent, papszMetadata[i] );
+            if(bJson)
+            {
+                if(bIsxml)
+                    poValue = json_object_new_string( papszMetadata[i] );
+                else
+                {
+                    pszValue = CPLParseNameValue( papszMetadata[i], &pszKey );
+                    poValue = json_object_new_string( pszValue );
+                    json_object_object_add( poDomain, pszKey, poValue );
+                    CPLFree( pszKey );
+                }
+            }
             else
-                printf( "%s  %s\n", pszIndent, papszMetadata[i] );
+            {
+                if (bIsxml)
+                    printf( "%s%s\n", pszIndent, papszMetadata[i] );
+                else
+                    printf( "%s  %s\n", pszIndent, papszMetadata[i] );
+            
+            }
+        }
+        if(bJson)
+        {
+            if(bIsxml)
+                json_object_object_add( poMetadata, pszDomain, poValue );
+            else
+            {
+                if(pszDomain == NULL)
+                    json_object_object_add( poMetadata, "", poDomain );
+                else
+                    json_object_object_add( poMetadata, pszDomain, poDomain );
+            }
         }
     }
+    
 }
 
 /************************************************************************/
@@ -837,7 +1472,9 @@ static void GDALInfoReportMetadata( GDALMajorObjectH hObject,
                                     int bListMDD,
                                     int bShowMetadata,
                                     char **papszExtraMDDomains,
-                                    int bIsBand )
+                                    int bIsBand,
+                                    int bJson,
+                                    json_object *poMetadata )
 {
     const char* pszIndent = "";
     if( bIsBand )
@@ -850,17 +1487,39 @@ static void GDALInfoReportMetadata( GDALMajorObjectH hObject,
     {
         char** papszMDDList = GDALGetMetadataDomainList( hObject );
         char** papszIter = papszMDDList;
+        json_object *poMDD = NULL;
+        json_object *poListMDD = NULL;
+        if( bJson )
+            poListMDD = json_object_new_array();
 
         if( papszMDDList != NULL )
-            printf( "%sMetadata domains:\n", pszIndent );
+        {
+            if(!bJson)
+                printf( "%sMetadata domains:\n", pszIndent );
+        }
+        
         while( papszIter != NULL && *papszIter != NULL )
         {
             if( EQUAL(*papszIter, "") )
-                printf( "%s  (default)\n", pszIndent);
+            {
+                if(bJson)
+                    poMDD = json_object_new_string( *papszIter );
+                else
+                    printf( "%s  (default)\n", pszIndent);
+            }
             else
-                printf( "%s  %s\n", pszIndent, *papszIter );
+            {
+                if(bJson)
+                    poMDD = json_object_new_string( *papszIter );
+                else
+                    printf( "%s  %s\n", pszIndent, *papszIter );
+            }
+            if(bJson)
+                json_object_array_add( poListMDD, poMDD );
             papszIter ++;
         }
+        if(bJson)
+            json_object_object_add( poMetadata, "metadataDomains", poListMDD );
         CSLDestroy(papszMDDList);
     }
 
@@ -870,7 +1529,7 @@ static void GDALInfoReportMetadata( GDALMajorObjectH hObject,
     /* -------------------------------------------------------------------- */
     /*      Report default Metadata domain.                                 */
     /* -------------------------------------------------------------------- */
-    GDALInfoPrintMetadata( hObject, NULL, "Metadata", pszIndent );
+    GDALInfoPrintMetadata( hObject, NULL, "Metadata", pszIndent, bJson, poMetadata );
 
     /* -------------------------------------------------------------------- */
     /*      Report extra Metadata domains                                   */
@@ -908,7 +1567,10 @@ static void GDALInfoReportMetadata( GDALMajorObjectH hObject,
         {
             char pszDisplayedname[256];
             snprintf(pszDisplayedname, 256, "Metadata (%s)", papszExtraMDDomainsExpanded[iMDD]);
-            GDALInfoPrintMetadata( hObject, papszExtraMDDomainsExpanded[iMDD], pszDisplayedname, pszIndent );
+            if(bJson)
+                GDALInfoPrintMetadata( hObject, papszExtraMDDomainsExpanded[iMDD], papszExtraMDDomainsExpanded[iMDD], pszIndent, bJson, poMetadata );
+            else
+                GDALInfoPrintMetadata( hObject, papszExtraMDDomainsExpanded[iMDD], pszDisplayedname, pszIndent, bJson, poMetadata );
         }
 
         CSLDestroy(papszExtraMDDomainsExpanded);
@@ -917,13 +1579,13 @@ static void GDALInfoReportMetadata( GDALMajorObjectH hObject,
     /* -------------------------------------------------------------------- */
     /*      Report various named metadata domains.                          */
     /* -------------------------------------------------------------------- */
-    GDALInfoPrintMetadata( hObject, "IMAGE_STRUCTURE", "Image Structure Metadata", pszIndent );
+    GDALInfoPrintMetadata( hObject, "IMAGE_STRUCTURE", "Image Structure Metadata", pszIndent, bJson, poMetadata );
 
     if (!bIsBand)
     {
-        GDALInfoPrintMetadata( hObject, "SUBDATASETS", "Subdatasets", pszIndent );
-        GDALInfoPrintMetadata( hObject, "GEOLOCATION", "Geolocation", pszIndent );
-        GDALInfoPrintMetadata( hObject, "RPC", "RPC Metadata", pszIndent );
+        GDALInfoPrintMetadata( hObject, "SUBDATASETS", "Subdatasets", pszIndent, bJson, poMetadata );
+        GDALInfoPrintMetadata( hObject, "GEOLOCATION", "Geolocation", pszIndent, bJson, poMetadata );
+        GDALInfoPrintMetadata( hObject, "RPC", "RPC Metadata", pszIndent, bJson, poMetadata );
     }
 
 }
diff --git a/apps/gdalwarp.cpp b/apps/gdalwarp.cpp
index 3f22127..434618c 100644
--- a/apps/gdalwarp.cpp
+++ b/apps/gdalwarp.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarp.cpp 29144 2015-05-04 09:22:47Z rouault $
+ * $Id: gdalwarp.cpp 29153 2015-05-04 17:51:41Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Test program for high performance warper API.
@@ -37,7 +37,7 @@
 #include "gdal_priv.h"
 #include <vector>
 
-CPL_CVSID("$Id: gdalwarp.cpp 29144 2015-05-04 09:22:47Z rouault $");
+CPL_CVSID("$Id: gdalwarp.cpp 29153 2015-05-04 17:51:41Z rouault $");
 
 static void
 LoadCutline( const char *pszCutlineDSName, const char *pszCLayer, 
@@ -364,6 +364,198 @@ char *SanitizeSRS( const char *pszUserInput )
     return pszResult;
 }
 
+#ifdef OGR_ENABLED
+
+static double GetAverageSegmentLength(OGRGeometryH hGeom)
+{
+    if( hGeom == NULL )
+        return 0;
+    switch(wkbFlatten(OGR_G_GetGeometryType(hGeom)))
+    {
+        case wkbLineString:
+        {
+            if( OGR_G_GetPointCount(hGeom) == 0 )
+                return 0;
+            double dfSum = 0;
+            for(int i=0;i<OGR_G_GetPointCount(hGeom)-1;i++)
+            {
+                double dfX1 = OGR_G_GetX(hGeom, i);
+                double dfY1 = OGR_G_GetY(hGeom, i);
+                double dfX2 = OGR_G_GetX(hGeom, i+1);
+                double dfY2 = OGR_G_GetY(hGeom, i+1);
+                double dfDX = dfX2 - dfX1;
+                double dfDY = dfY2 - dfY1;
+                dfSum += sqrt(dfDX * dfDX + dfDY * dfDY);
+            }
+            return dfSum / OGR_G_GetPointCount(hGeom);
+        }
+
+        case wkbPolygon:
+        case wkbMultiPolygon:
+        case wkbMultiLineString:
+        case wkbGeometryCollection:
+        {
+            if( OGR_G_GetGeometryCount(hGeom) == 0 )
+                return 0;
+            double dfSum = 0;
+            for(int i=0; i< OGR_G_GetGeometryCount(hGeom); i++)
+            {
+                dfSum += GetAverageSegmentLength(OGR_G_GetGeometryRef(hGeom, i));
+            }
+            return dfSum / OGR_G_GetGeometryCount(hGeom);
+        }
+        
+        default:
+            return 0;
+    }
+}
+
+/************************************************************************/
+/*                           CropToCutline()                            */
+/************************************************************************/
+
+static void CropToCutline( void* hCutline, char** papszTO, char** papszSrcFiles,
+                           char** papszOpenOptions,
+                           double& dfMinX, double& dfMinY, double& dfMaxX, double &dfMaxY )
+{
+    OGRGeometryH hCutlineGeom = OGR_G_Clone( (OGRGeometryH) hCutline );
+    OGRSpatialReferenceH hCutlineSRS = OGR_G_GetSpatialReference( hCutlineGeom );
+    const char *pszThisTargetSRS = CSLFetchNameValue( papszTO, "DST_SRS" );
+    const char *pszThisSourceSRS = CSLFetchNameValue(papszTO, "SRC_SRS");
+    OGRCoordinateTransformationH hCTCutlineToSrc = NULL;
+    OGRCoordinateTransformationH hCTSrcToDst = NULL;
+    OGRSpatialReferenceH hSrcSRS = NULL, hDstSRS = NULL;
+
+    if( pszThisSourceSRS != NULL )
+    {
+        hSrcSRS = OSRNewSpatialReference(NULL);
+        if( OSRImportFromWkt( hSrcSRS, (char **)&pszThisSourceSRS ) != CE_None )
+        {
+            fprintf(stderr, "Cannot compute bounding box of cutline.\n");
+            GDALExit(1);
+        }
+    }
+    else if( papszSrcFiles[0] != NULL )
+    {
+        GDALDatasetH hSrcDS = GDALOpenEx( papszSrcFiles[0], GDAL_OF_RASTER, NULL,
+                    (const char* const* )papszOpenOptions, NULL );
+        if (hSrcDS == NULL)
+        {
+            fprintf(stderr, "Cannot compute bounding box of cutline.\n");
+            GDALExit(1);
+        }
+
+        const char *pszProjection = NULL;
+
+        if( GDALGetProjectionRef( hSrcDS ) != NULL
+            && strlen(GDALGetProjectionRef( hSrcDS )) > 0 )
+            pszProjection = GDALGetProjectionRef( hSrcDS );
+        else if( GDALGetGCPProjection( hSrcDS ) != NULL )
+            pszProjection = GDALGetGCPProjection( hSrcDS );
+
+        if( pszProjection == NULL )
+        {
+            fprintf(stderr, "Cannot compute bounding box of cutline.\n");
+            GDALExit(1);
+        }
+
+        hSrcSRS = OSRNewSpatialReference(NULL);
+        if( OSRImportFromWkt( hSrcSRS, (char **)&pszProjection ) != CE_None )
+        {
+            fprintf(stderr, "Cannot compute bounding box of cutline.\n");
+            GDALExit(1);
+        }
+
+        GDALClose(hSrcDS);
+    }
+    else
+    {
+        fprintf(stderr, "Cannot compute bounding box of cutline.\n");
+        GDALExit(1);
+    }
+
+    if ( pszThisTargetSRS != NULL )
+    {
+        hDstSRS = OSRNewSpatialReference(NULL);
+        if( OSRImportFromWkt( hDstSRS, (char **)&pszThisTargetSRS ) != CE_None )
+        {
+            fprintf(stderr, "Cannot compute bounding box of cutline.\n");
+            GDALExit(1);
+        }
+    }
+    else
+        hDstSRS = OSRClone(hSrcSRS);
+
+    OGRSpatialReferenceH hCutlineOrTargetSRS = hCutlineSRS ? hCutlineSRS : hDstSRS;
+
+    if( !OSRIsSame(hCutlineOrTargetSRS, hSrcSRS) )
+        hCTCutlineToSrc = OCTNewCoordinateTransformation(hCutlineOrTargetSRS, hSrcSRS);
+    if( !OSRIsSame(hSrcSRS, hDstSRS) )
+        hCTSrcToDst = OCTNewCoordinateTransformation(hSrcSRS, hDstSRS);
+
+    OSRDestroySpatialReference(hSrcSRS);
+    hSrcSRS = NULL;
+
+    OSRDestroySpatialReference(hDstSRS);
+    hDstSRS = NULL;
+
+    // Reproject cutline to target SRS, by doing intermediate vertex densifications
+    // in source SRS.
+    if( hCTSrcToDst != NULL || hCTCutlineToSrc != NULL )
+    {
+        OGREnvelope sLastEnvelope, sCurEnvelope;
+        OGRGeometryH hTransformedGeom = NULL;
+        OGRGeometryH hGeomInSrcSRS = OGR_G_Clone(hCutlineGeom);
+        if( hCTCutlineToSrc != NULL )
+            OGR_G_Transform( hGeomInSrcSRS, hCTCutlineToSrc );
+
+        for(int nIter=0;nIter<10;nIter++)
+        {
+            if( hTransformedGeom != NULL )
+                OGR_G_DestroyGeometry(hTransformedGeom);
+            hTransformedGeom = OGR_G_Clone(hGeomInSrcSRS);
+            if( hCTSrcToDst != NULL )
+                OGR_G_Transform( hTransformedGeom, hCTSrcToDst );
+            OGR_G_GetEnvelope(hTransformedGeom, &sCurEnvelope);
+            if( nIter > 0 || hCTSrcToDst == NULL )
+            {
+                if( sCurEnvelope.MinX == sLastEnvelope.MinX &&
+                    sCurEnvelope.MinY == sLastEnvelope.MinY &&
+                    sCurEnvelope.MaxX == sLastEnvelope.MaxX &&
+                    sCurEnvelope.MaxY == sLastEnvelope.MaxY )
+                {
+                    break;
+                }
+            }
+            double dfAverageSegmentLength = GetAverageSegmentLength(hGeomInSrcSRS);
+            OGR_G_Segmentize(hGeomInSrcSRS, dfAverageSegmentLength/4);
+
+            memcpy(&sLastEnvelope, &sCurEnvelope, sizeof(OGREnvelope));
+        }
+        
+        OGR_G_DestroyGeometry(hGeomInSrcSRS);
+
+        OGR_G_DestroyGeometry(hCutlineGeom);
+        hCutlineGeom = hTransformedGeom;
+    }
+
+    if( hCTCutlineToSrc) 
+        OCTDestroyCoordinateTransformation(hCTCutlineToSrc);
+    if( hCTSrcToDst )
+        OCTDestroyCoordinateTransformation(hCTSrcToDst);
+
+    OGREnvelope sEnvelope;
+    OGR_G_GetEnvelope(hCutlineGeom, &sEnvelope);
+
+    dfMinX = sEnvelope.MinX;
+    dfMinY = sEnvelope.MinY;
+    dfMaxX = sEnvelope.MaxX;
+    dfMaxY = sEnvelope.MaxY;
+    
+    OGR_G_DestroyGeometry(hCutlineGeom);
+}
+#endif /* OGR_ENABLED */
+
 /************************************************************************/
 /*                                main()                                */
 /************************************************************************/
@@ -990,90 +1182,8 @@ int main( int argc, char ** argv )
 #ifdef OGR_ENABLED
     if ( bCropToCutline && hCutline != NULL )
     {
-        OGRGeometryH hCutlineGeom = OGR_G_Clone( (OGRGeometryH) hCutline );
-        OGRSpatialReferenceH hCutlineSRS = OGR_G_GetSpatialReference( hCutlineGeom );
-        const char *pszThisTargetSRS = CSLFetchNameValue( papszTO, "DST_SRS" );
-        OGRCoordinateTransformationH hCT = NULL;
-        if (hCutlineSRS == NULL)
-        {
-            /* We suppose it is in target coordinates */
-        }
-        else if (pszThisTargetSRS != NULL)
-        {
-            OGRSpatialReferenceH hTargetSRS = OSRNewSpatialReference(NULL);
-            if( OSRImportFromWkt( hTargetSRS, (char **)&pszThisTargetSRS ) != CE_None )
-            {
-                fprintf(stderr, "Cannot compute bounding box of cutline.\n");
-                GDALExit(1);
-            }
-
-            hCT = OCTNewCoordinateTransformation(hCutlineSRS, hTargetSRS);
-
-            OSRDestroySpatialReference(hTargetSRS);
-        }
-        else if (pszThisTargetSRS == NULL)
-        {
-            if (papszSrcFiles[0] != NULL)
-            {
-                GDALDatasetH hSrcDS = GDALOpenEx( papszSrcFiles[0], GDAL_OF_RASTER, NULL,
-                           (const char* const* )papszOpenOptions, NULL );
-                if (hSrcDS == NULL)
-                {
-                    fprintf(stderr, "Cannot compute bounding box of cutline.\n");
-                    GDALExit(1);
-                }
-
-                OGRSpatialReferenceH  hRasterSRS = NULL;
-                const char *pszProjection = NULL;
-
-                if( GDALGetProjectionRef( hSrcDS ) != NULL
-                    && strlen(GDALGetProjectionRef( hSrcDS )) > 0 )
-                    pszProjection = GDALGetProjectionRef( hSrcDS );
-                else if( GDALGetGCPProjection( hSrcDS ) != NULL )
-                    pszProjection = GDALGetGCPProjection( hSrcDS );
-
-                if( pszProjection == NULL )
-                {
-                    fprintf(stderr, "Cannot compute bounding box of cutline.\n");
-                    GDALExit(1);
-                }
-
-                hRasterSRS = OSRNewSpatialReference(NULL);
-                if( OSRImportFromWkt( hRasterSRS, (char **)&pszProjection ) != CE_None )
-                {
-                    fprintf(stderr, "Cannot compute bounding box of cutline.\n");
-                    GDALExit(1);
-                }
-
-                hCT = OCTNewCoordinateTransformation(hCutlineSRS, hRasterSRS);
-
-                OSRDestroySpatialReference(hRasterSRS);
-
-                GDALClose(hSrcDS);
-            }
-            else
-            {
-                fprintf(stderr, "Cannot compute bounding box of cutline.\n");
-                GDALExit(1);
-            }
-        }
-
-        if (hCT)
-        {
-            OGR_G_Transform( hCutlineGeom, hCT );
-
-            OCTDestroyCoordinateTransformation(hCT);
-        }
-
-        OGREnvelope sEnvelope;
-        OGR_G_GetEnvelope(hCutlineGeom, &sEnvelope);
-
-        dfMinX = sEnvelope.MinX;
-        dfMinY = sEnvelope.MinY;
-        dfMaxX = sEnvelope.MaxX;
-        dfMaxY = sEnvelope.MaxY;
-        
-        OGR_G_DestroyGeometry(hCutlineGeom);
+        CropToCutline( hCutline, papszTO, papszSrcFiles, papszOpenOptions,
+                       dfMinX, dfMinY, dfMaxX, dfMaxY );
     }
 #endif
     
diff --git a/apps/makefile.vc b/apps/makefile.vc
index b29c647..78b564b 100644
--- a/apps/makefile.vc
+++ b/apps/makefile.vc
@@ -5,7 +5,7 @@ XTRAOBJ =	$(SETARGV)
 
 LIBS	=	$(GDAL_ROOT)\gdal_i.lib
 
-XTRAFLAGS =	-I..\gcore -I..\port -I..\frmts\vrt -I..\alg -I..\ogr -I..\ogr\ogrsf_frmts  $(GEOS_CFLAGS)
+XTRAFLAGS =	-I..\gcore -I..\port -I..\frmts\vrt -I..\alg -I..\ogr -I..\ogr\ogrsf_frmts  $(GEOS_CFLAGS) -I..\ogr\ogrsf_frmts\geojson\libjson -I..\ogr\ogrsf_frmts\geojson
 
 !INCLUDE ..\nmake.opt
 
diff --git a/apps/ogr2ogr.cpp b/apps/ogr2ogr.cpp
index 9b0ea8d..0461c95 100644
--- a/apps/ogr2ogr.cpp
+++ b/apps/ogr2ogr.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr2ogr.cpp 29012 2015-04-25 17:27:37Z rouault $
+ * $Id: ogr2ogr.cpp 29236 2015-05-22 19:39:48Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Simple client for translating between formats.
@@ -39,10 +39,11 @@
 #include <map>
 #include <vector>
 
-CPL_CVSID("$Id: ogr2ogr.cpp 29012 2015-04-25 17:27:37Z rouault $");
+CPL_CVSID("$Id: ogr2ogr.cpp 29236 2015-05-22 19:39:48Z rouault $");
 
 static int bSkipFailures = FALSE;
 static int bLayerTransaction = -1;
+static int bForceTransaction = FALSE;
 static int nGroupTransactions = 20000;
 static GIntBig nFIDToFetch = OGRNullFID;
 
@@ -1174,10 +1175,10 @@ int main( int nArgc, char ** papszArgv )
             else
                 nGroupTransactions = atoi(papszArgv[iArg]);
         }
-        /* Undocumented. Just a provision. Default behaviour should be OK */
         else if ( EQUAL(papszArgv[iArg],"-ds_transaction") )
         {
             bLayerTransaction = FALSE;
+            bForceTransaction = TRUE;
         }
         /* Undocumented. Just a provision. Default behaviour should be OK */
         else if ( EQUAL(papszArgv[iArg],"-lyr_transaction") )
@@ -1754,6 +1755,11 @@ int main( int nArgc, char ** papszArgv )
                     pszFormat );
             exit( 1 );
         }
+        
+        if( papszDestOpenOptions != NULL )
+        {
+            fprintf(stderr, "-doo ignored when creating the output datasource.\n");
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Special case to improve user experience when translating        */
@@ -1930,7 +1936,7 @@ int main( int nArgc, char ** papszArgv )
     if( nGroupTransactions )
     {
         if( !bLayerTransaction )
-            poODS->StartTransaction();
+            poODS->StartTransaction(bForceTransaction);
     }
 
 /* -------------------------------------------------------------------- */
@@ -2510,7 +2516,7 @@ static void Usage(const char* pszAdditionalMsg, int bShort)
             "               [-dim 2|3|layer_dim] [layer [layer ...]]\n"
             "\n"
             "Advanced options :\n"
-            "               [-gt n]\n"
+            "               [-gt n] [-ds_transaction]\n"
             "               [[-oo NAME=VALUE] ...] [[-doo NAME=VALUE] ...]\n"
             "               [-clipsrc [xmin ymin xmax ymax]|WKT|datasource|spat_extent]\n"
             "               [-clipsrcsql sql_statement] [-clipsrclayer layer]\n"
@@ -2564,7 +2570,7 @@ static void Usage(const char* pszAdditionalMsg, int bShort)
             " -sql statement: Execute given SQL statement and save result.\n"
             " -dialect value: select a dialect, usually OGRSQL to avoid native sql.\n"
             " -skipfailures: skip features or layers that fail to convert\n"
-            " -gt n: group n features per transaction (default 20000)\n"
+            " -gt n: group n features per transaction (default 20000). n can be set to unlimited\n"
             " -spat xmin ymin xmax ymax: spatial query extents\n"
             " -simplify tolerance: distance tolerance for simplification.\n"
             " -segmentize max_dist: maximum distance between 2 nodes.\n"
@@ -3749,21 +3755,13 @@ int LayerTranslator::Translate( TargetLayerInfo* psInfo,
                                         psInfo->iRequestedSrcGeomField);
             else
                 poSrcGeometry = poFeature->GetGeometryRef();
-            if (poSrcGeometry)
-            {
-                switch (wkbFlatten(poSrcGeometry->getGeometryType()))
-                {
-                    case wkbMultiPoint:
-                    case wkbMultiLineString:
-                    case wkbMultiPolygon:
-                    case wkbGeometryCollection:
-                        nParts = ((OGRGeometryCollection*)poSrcGeometry)->getNumGeometries();
-                        nIters = nParts;
-                        if (nIters == 0)
-                            nIters = 1;
-                    default:
-                        break;
-                }
+            if (poSrcGeometry &&
+                OGR_GT_IsSubClassOf(poSrcGeometry->getGeometryType(), wkbGeometryCollection) )
+            {
+                nParts = ((OGRGeometryCollection*)poSrcGeometry)->getNumGeometries();
+                nIters = nParts;
+                if (nIters == 0)
+                    nIters = 1;
             }
         }
 
@@ -3779,7 +3777,7 @@ int LayerTranslator::Translate( TargetLayerInfo* psInfo,
                 else
                 {
                     poODS->CommitTransaction();
-                    poODS->StartTransaction();
+                    poODS->StartTransaction(bForceTransaction);
                 }
                 nFeaturesInTransaction = 0;
             }
@@ -3933,6 +3931,9 @@ int LayerTranslator::Translate( TargetLayerInfo* psInfo,
 
                 if (poClipDst)
                 {
+                    if( poDstGeometry == NULL )
+                        goto end_loop;
+
                     OGRGeometry* poClipped = poDstGeometry->Intersection(poClipDst);
                     if (poClipped == NULL || poClipped->IsEmpty())
                     {
diff --git a/apps/ogr_utilities.dox b/apps/ogr_utilities.dox
index dadd4cb..5a89191 100644
--- a/apps/ogr_utilities.dox
+++ b/apps/ogr_utilities.dox
@@ -297,7 +297,12 @@ Advanced options :
 <dt> <b>-oo</b> <em>NAME=VALUE</em>:</dt><dd>(starting with GDAL 2.0) Input dataset open option (format specific)</dd>
 <dt> <b>-doo</b> <em>NAME=VALUE</em>:</dt><dd>(starting with GDAL 2.0) Destination dataset open option (format specific), only valid in -update mode</dd>
 <dt> <b>-gt</b> <em>n</em>:</dt><dd> group <em>n</em> features per transaction (default 20000 in OGR 1.11, 200 in previous releases). Increase the value
-for better performance when writing into DBMS drivers that have transaction support.</dd>
+for better performance when writing into DBMS drivers that have transaction support. Starting with GDAL 2.0,
+n can be set to unlimited to load the data into a single transaction.</dd>
+<dt> <b>-ds_transaction</b>:</dt><dd>(starting with GDAL 2.0) Force the use of
+a dataset level transaction (for drivers that support such mechanism),
+especially for drivers such as FileGDB that only support dataset level transaction
+in emulation mode.</dd>
 <dt> <b>-clipsrc</b><em> [xmin ymin xmax ymax]|WKT|datasource|spat_extent</em>:
 </dt><dd> (starting with GDAL 1.7.0) clip geometries to the specified bounding
 box (expressed in source SRS), WKT geometry (POLYGON or MULTIPOLYGON), from a
diff --git a/configure b/configure
index 0b3e9bb..74b2748 100755
--- a/configure
+++ b/configure
@@ -6572,7 +6572,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu)
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-netbsd* | netbsdelf*-gnu)
+netbsd*)
   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
     lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
   else
@@ -9960,9 +9960,6 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie
   openbsd*)
     with_gnu_ld=no
     ;;
-  linux* | k*bsd*-gnu | gnu*)
-    link_all_deplibs=no
-    ;;
   esac
 
   ld_shlibs=yes
@@ -10185,7 +10182,7 @@ _LT_EOF
       fi
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
 	archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
 	wlarc=
@@ -10362,7 +10359,6 @@ _LT_EOF
 	if test "$aix_use_runtimelinking" = yes; then
 	  shared_flag="$shared_flag "'${wl}-G'
 	fi
-	link_all_deplibs=no
       else
 	# not using gcc
 	if test "$host_cpu" = ia64; then
@@ -10819,7 +10815,7 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; }
       link_all_deplibs=yes
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
 	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
       else
@@ -11672,7 +11668,6 @@ gnu*)
   library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
   soname_spec='${libname}${release}${shared_ext}$major'
   shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
   hardcode_into_libs=yes
   ;;
 
@@ -11856,18 +11851,6 @@ fi
   dynamic_linker='GNU/Linux ld.so'
   ;;
 
-netbsdelf*-gnu)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  dynamic_linker='NetBSD ld.elf_so'
-  ;;
-
 netbsd*)
   version_type=sunos
   need_lib_prefix=no
@@ -14702,7 +14685,7 @@ lt_prog_compiler_static_CXX=
 	    ;;
 	esac
 	;;
-      netbsd* | netbsdelf*-gnu)
+      netbsd*)
 	;;
       *qnx* | *nto*)
         # QNX uses GNU C++, but need to define -shared option too, otherwise
@@ -15071,9 +15054,6 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie
       ;;
     esac
     ;;
-  linux* | k*bsd*-gnu | gnu*)
-    link_all_deplibs_CXX=no
-    ;;
   *)
     export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
     ;;
@@ -15521,7 +15501,6 @@ gnu*)
   library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
   soname_spec='${libname}${release}${shared_ext}$major'
   shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
   hardcode_into_libs=yes
   ;;
 
@@ -15705,18 +15684,6 @@ fi
   dynamic_linker='GNU/Linux ld.so'
   ;;
 
-netbsdelf*-gnu)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  dynamic_linker='NetBSD ld.elf_so'
-  ;;
-
 netbsd*)
   version_type=sunos
   need_lib_prefix=no
@@ -28928,6 +28895,7 @@ elif test "x$with_python" != "x" -a "$with_python" != "no" ; then
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5
 $as_echo "enabled" >&6; }
 else
+  PYTHON=""
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
 $as_echo "disabled" >&6; }
 fi
diff --git a/configure.in b/configure.in
index 86919a3..000ebdb 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: configure.in 28874 2015-04-08 15:10:44Z dron $
+dnl $Id: configure.in 29175 2015-05-09 14:08:22Z rouault $
 dnl
 dnl Project:  GDAL
 dnl Purpose:  Configure source file.
@@ -4025,6 +4025,7 @@ elif test "x$with_python" != "x" -a "$with_python" != "no" ; then
   fi
   AC_MSG_RESULT([enabled])
 else
+  PYTHON=""
   AC_MSG_RESULT([disabled])
 fi
 
diff --git a/frmts/blx/blx.c b/frmts/blx/blx.c
index 9c6bec8..8f6b46c 100644
--- a/frmts/blx/blx.c
+++ b/frmts/blx/blx.c
@@ -30,6 +30,8 @@
 #include <string.h>
 #include <stdlib.h>
 
+#include "cpl_port.h"
+
 /* Constants */
 #define MAXLEVELS 5
 #define MAXCOMPONENTS 4
diff --git a/frmts/gif/gifabstractdataset.cpp b/frmts/gif/gifabstractdataset.cpp
index 00723b0..c9d2b3b 100644
--- a/frmts/gif/gifabstractdataset.cpp
+++ b/frmts/gif/gifabstractdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gifabstractdataset.cpp 28283 2015-01-03 20:08:00Z rouault $
+ * $Id: gifabstractdataset.cpp 29222 2015-05-21 15:06:39Z rouault $
  *
  * Project:  GIF Driver
  * Purpose:  GIF Abstract Dataset
@@ -29,7 +29,7 @@
 
 #include "gifabstractdataset.h"
 
-CPL_CVSID("$Id: gifabstractdataset.cpp 28283 2015-01-03 20:08:00Z rouault $");
+CPL_CVSID("$Id: gifabstractdataset.cpp 29222 2015-05-21 15:06:39Z rouault $");
 
 static const int InterlacedOffset[] = { 0, 4, 2, 1 }; 
 static const int InterlacedJumps[] = { 8, 8, 4, 2 };  
@@ -324,19 +324,47 @@ int GIFAbstractDataset::Identify( GDALOpenInfo * poOpenInfo )
 }
 
 /************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char **GIFAbstractDataset::GetFileList()
+
+{
+    char **papszFileList = GDALPamDataset::GetFileList();
+
+    if (osWldFilename.size() != 0 &&
+        CSLFindString(papszFileList, osWldFilename) == -1)
+    {
+        papszFileList = CSLAddString( papszFileList, osWldFilename );
+    }
+
+    return papszFileList;
+}
+
+/************************************************************************/
 /*                         DetectGeoreferencing()                       */
 /************************************************************************/
 
 void GIFAbstractDataset::DetectGeoreferencing( GDALOpenInfo * poOpenInfo )
 {
+    char* pszWldFilename = NULL;
+
     bGeoTransformValid =
         GDALReadWorldFile2( poOpenInfo->pszFilename, NULL,
-                           adfGeoTransform, poOpenInfo->GetSiblingFiles(), NULL );
+                            adfGeoTransform, poOpenInfo->GetSiblingFiles(), 
+                            &pszWldFilename );
     if ( !bGeoTransformValid )
     {
         bGeoTransformValid =
             GDALReadWorldFile2( poOpenInfo->pszFilename, ".wld",
-                               adfGeoTransform, poOpenInfo->GetSiblingFiles(), NULL );
+                                adfGeoTransform, poOpenInfo->GetSiblingFiles(),
+                                &pszWldFilename );
+    }
+
+    if (pszWldFilename)
+    {
+        osWldFilename = pszWldFilename;
+        CPLFree(pszWldFilename);
     }
 }
 
diff --git a/frmts/gif/gifabstractdataset.h b/frmts/gif/gifabstractdataset.h
index fe19512..66c9ddf 100644
--- a/frmts/gif/gifabstractdataset.h
+++ b/frmts/gif/gifabstractdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gifabstractdataset.h 28279 2015-01-03 14:37:52Z rouault $
+ * $Id: gifabstractdataset.h 29222 2015-05-21 15:06:39Z rouault $
  *
  * Project:  GIF Driver
  * Purpose:  GIF Abstract Dataset
@@ -61,6 +61,8 @@ class GIFAbstractDataset : public GDALPamDataset
     int         bHasReadXMPMetadata;
     void        CollectXMPMetadata();
 
+    CPLString   osWldFilename;
+
     void        DetectGeoreferencing( GDALOpenInfo * poOpenInfo );
 
   public:
@@ -76,6 +78,8 @@ class GIFAbstractDataset : public GDALPamDataset
     virtual char      **GetMetadataDomainList();
     virtual char  **GetMetadata( const char * pszDomain = "" );
 
+    virtual char **GetFileList(void);
+
     static int          Identify( GDALOpenInfo * );
 
     static GifFileType* myDGifOpen( void *userPtr, InputFunc readFunc );
diff --git a/frmts/gtiff/geotiff.cpp b/frmts/gtiff/geotiff.cpp
index d0d6294..22dc7e4 100644
--- a/frmts/gtiff/geotiff.cpp
+++ b/frmts/gtiff/geotiff.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geotiff.cpp 29129 2015-05-03 13:24:20Z rouault $
+ * $Id: geotiff.cpp 29228 2015-05-21 19:45:55Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  GDAL GeoTIFF support.
@@ -63,7 +63,7 @@
 #include "tiffiop.h"
 #endif
 
-CPL_CVSID("$Id: geotiff.cpp 29129 2015-05-03 13:24:20Z rouault $");
+CPL_CVSID("$Id: geotiff.cpp 29228 2015-05-21 19:45:55Z rouault $");
 
 #if SIZEOF_VOIDP == 4
 static int bGlobalStripIntegerOverflow = FALSE;
@@ -5351,13 +5351,17 @@ int GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
     /*
     ** Perform tile fill if needed.
     */
-    if( bNeedTileFill )
+    // TODO: we should also handle the case of nBitsPerSample == 12
+    // but this is more involved...
+    if( bNeedTileFill && nBitsPerSample == 8 )
     {
         int nRightPixelsToFill = 0;
         int nBottomPixelsToFill = 0;
-        int nPixelSize = cc / (nBlockXSize * nBlockYSize);
         unsigned int iX, iY, iSrcX, iSrcY;
-        
+        int nComponents = 1;
+        if( nPlanarConfig == PLANARCONFIG_CONTIG )
+            nComponents = nBands;
+
         CPLDebug( "GTiff", "Filling out jpeg edge tile on write." );
 
         if( iColumn == nBlocksPerRow - 1 )
@@ -5372,9 +5376,9 @@ int GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
         {
             for( iY = 0; iY < nBlockYSize; iY++ )
             {
-                memcpy( pabyData + (nBlockXSize * iY + iX) * nPixelSize, 
-                        pabyData + (nBlockXSize * iY + iSrcX) * nPixelSize, 
-                        nPixelSize );
+                memcpy( pabyData + (nBlockXSize * iY + iX) * nComponents, 
+                        pabyData + (nBlockXSize * iY + iSrcX) * nComponents, 
+                        nComponents );
             }
         }
 
@@ -5382,9 +5386,9 @@ int GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
         iSrcY = nBlockYSize - nBottomPixelsToFill - 1;
         for( iY = iSrcY+1; iY < nBlockYSize; iY++ )
         {
-            memcpy( pabyData + nBlockXSize * nPixelSize * iY, 
-                    pabyData + nBlockXSize * nPixelSize * iSrcY, 
-                    nPixelSize * nBlockXSize );
+            memcpy( pabyData + nBlockXSize * nComponents * iY, 
+                    pabyData + nBlockXSize * nComponents * iSrcY, 
+                    nBlockXSize * nComponents );
         }
     }
 
diff --git a/frmts/hdf4/hdf4dataset.cpp b/frmts/hdf4/hdf4dataset.cpp
index a15edcc..bb4156a 100644
--- a/frmts/hdf4/hdf4dataset.cpp
+++ b/frmts/hdf4/hdf4dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf4dataset.cpp 28901 2015-04-14 10:10:32Z rouault $
+ * $Id: hdf4dataset.cpp 29208 2015-05-19 13:54:59Z rouault $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  HDF4 Datasets. Open HDF4 file, fetch metadata and list of
@@ -42,7 +42,7 @@
 #include "hdf4compat.h"
 #include "hdf4dataset.h"
 
-CPL_CVSID("$Id: hdf4dataset.cpp 28901 2015-04-14 10:10:32Z rouault $");
+CPL_CVSID("$Id: hdf4dataset.cpp 29208 2015-05-19 13:54:59Z rouault $");
 
 CPL_C_START
 void	GDALRegister_HDF4(void);
@@ -295,11 +295,11 @@ double HDF4Dataset::AnyTypeToDouble( int32 iNumType, void *pData )
         case DFNT_UINT16:
             return (double)*(unsigned short *)pData;
         case DFNT_INT32:
-            return (double)*(long *)pData;
+            return (double)*(int *)pData;
         case DFNT_UINT32:
-            return (double)*(unsigned long *)pData;
+            return (double)*(unsigned int *)pData;
         case DFNT_INT64:
-            return (double)*(char *)pData;
+            return (double)*(char *)pData; // highly suspicious ! Should be GIntBig. But cannot verify
         case DFNT_UINT64:
             return (double)*(GIntBig *)pData;
         case DFNT_FLOAT32:
diff --git a/frmts/hdf4/hdf4imagedataset.cpp b/frmts/hdf4/hdf4imagedataset.cpp
index 92ce1e1..93869db 100644
--- a/frmts/hdf4/hdf4imagedataset.cpp
+++ b/frmts/hdf4/hdf4imagedataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf4imagedataset.cpp 28459 2015-02-12 13:48:21Z rouault $
+ * $Id: hdf4imagedataset.cpp 29212 2015-05-20 09:28:31Z rouault $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  Read subdatasets of HDF4 file.
@@ -47,7 +47,7 @@
 
 #include "nasakeywordhandler.h"
 
-CPL_CVSID("$Id: hdf4imagedataset.cpp 28459 2015-02-12 13:48:21Z rouault $");
+CPL_CVSID("$Id: hdf4imagedataset.cpp 29212 2015-05-20 09:28:31Z rouault $");
 
 CPL_C_START
 void    GDALRegister_HDF4(void);
@@ -1890,10 +1890,6 @@ void HDF4ImageDataset::GetGridAttrs( int32 hGD )
 /*      download.osgeo.org/gdal/data/hdf4/A2006005182000.L2_LAC_SST.x.hdf */
 /*                                                                      */
 /*      As reported in ticket #1895.                                    */
-/*                                                                      */
-/*      Note that we don't check that the dimensions of the latitude    */
-/*      and longitude exactly match the dimensions of the basedata,     */
-/*      though we ought to.                                             */
 /************************************************************************/
 
 void HDF4ImageDataset::ProcessModisSDSGeolocation(void)
@@ -1916,6 +1912,9 @@ void HDF4ImageDataset::ProcessModisSDSGeolocation(void)
     if ( SDfileinfo( hSD, &nDatasets, &nAttributes ) != 0 )
 	return;
 
+
+    int nLongitudeWidth = 0, nLongitudeHeight = 0;
+    int nLatitudeWidth = 0, nLatitudeHeight = 0;
     for( iDSIndex = 0; iDSIndex < nDatasets; iDSIndex++ )
     {
         int32	    iRank, iNumType, nAttrs, iSDS;
@@ -1928,10 +1927,24 @@ void HDF4ImageDataset::ProcessModisSDSGeolocation(void)
                        &nAttrs) == 0 )
         {
             if( EQUAL(szName,"latitude") )
+            {
                 iYIndex = iDSIndex;
+                if( iRank == 2 )
+                {
+                    nLatitudeWidth = aiDimSizes[1];
+                    nLatitudeHeight = aiDimSizes[0];
+                }
+            }
 
             if( EQUAL(szName,"longitude") )
+            {
                 iXIndex = iDSIndex;
+                if( iRank == 2 )
+                {
+                    nLongitudeWidth = aiDimSizes[1];
+                    nLongitudeHeight = aiDimSizes[0];
+                }
+            }
         }
 
         SDendaccess(iSDS);
@@ -1940,6 +1953,20 @@ void HDF4ImageDataset::ProcessModisSDSGeolocation(void)
     if( iXIndex == -1 || iYIndex == -1 )
         return;
 
+    int nPixelOffset = 0, nLineOffset = 0;
+    int nPixelStep = 1, nLineStep = 1;
+    if( nLongitudeWidth != nLatitudeWidth || nLongitudeHeight != nLatitudeHeight )
+    {
+        CPLDebug("HDF4", "Longitude and latitude subdatasets don't have same dimensions...");
+    }
+    else if( nLongitudeWidth > 0 && nLongitudeHeight > 0 )
+    {
+        nPixelStep = (int)(0.5 + 1.0 * nRasterXSize / nLongitudeWidth);
+        nLineStep = (int)(0.5 + 1.0 * nRasterYSize / nLongitudeHeight);
+        nPixelOffset = (nPixelStep-1) / 2;
+        nLineOffset = (nLineStep-1) / 2;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      We found geolocation information.  Record it as metadata.       */
 /* -------------------------------------------------------------------- */
@@ -1957,11 +1984,11 @@ void HDF4ImageDataset::ProcessModisSDSGeolocation(void)
     SetMetadataItem( "Y_DATASET", osWrk, "GEOLOCATION" );
     SetMetadataItem( "Y_BAND", "1" , "GEOLOCATION" );
 
-    SetMetadataItem( "PIXEL_OFFSET", "0", "GEOLOCATION" );
-    SetMetadataItem( "PIXEL_STEP", "1", "GEOLOCATION" );
+    SetMetadataItem( "PIXEL_OFFSET", CPLSPrintf("%d", nPixelOffset), "GEOLOCATION" );
+    SetMetadataItem( "PIXEL_STEP", CPLSPrintf("%d", nPixelStep), "GEOLOCATION" );
 
-    SetMetadataItem( "LINE_OFFSET", "0", "GEOLOCATION" );
-    SetMetadataItem( "LINE_STEP", "1", "GEOLOCATION" );
+    SetMetadataItem( "LINE_OFFSET", CPLSPrintf("%d", nLineOffset), "GEOLOCATION" );
+    SetMetadataItem( "LINE_STEP", CPLSPrintf("%d", nLineStep), "GEOLOCATION" );
 }
 
 /************************************************************************/
diff --git a/frmts/hfa/hfadataset.cpp b/frmts/hfa/hfadataset.cpp
index d9b302e..7ac2f95 100644
--- a/frmts/hfa/hfadataset.cpp
+++ b/frmts/hfa/hfadataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfadataset.cpp 28899 2015-04-14 09:27:00Z rouault $
+ * $Id: hfadataset.cpp 29206 2015-05-18 15:52:22Z rouault $
  *
  * Name:     hfadataset.cpp
  * Project:  Erdas Imagine Driver
@@ -35,7 +35,7 @@
 #include "ogr_spatialref.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: hfadataset.cpp 28899 2015-04-14 09:27:00Z rouault $");
+CPL_CVSID("$Id: hfadataset.cpp 29206 2015-05-18 15:52:22Z rouault $");
 
 CPL_C_START
 void	GDALRegister_HFA(void);
@@ -5011,12 +5011,11 @@ CPLErr HFADataset::ReadProjection()
 
     CPLFree( pszProjection );
 
-    if( !psDatum || !psPro ||
-        (psMapInfo == NULL && poMapInformation == NULL) ||
-        ((strlen(psDatum->datumname) == 0 || EQUAL(psDatum->datumname, "Unknown")) && 
-        (strlen(psPro->proName) == 0 || EQUAL(psPro->proName, "Unknown")) &&
-        (psMapInfo && (strlen(psMapInfo->proName) == 0 || EQUAL(psMapInfo->proName, "Unknown"))) && 
-        psPro->proZone == 0) )
+    if((psMapInfo == NULL && poMapInformation == NULL) ||
+       ((!psDatum || strlen(psDatum->datumname) == 0 || EQUAL(psDatum->datumname, "Unknown")) &&
+       (!psPro || strlen(psPro->proName) == 0 || EQUAL(psPro->proName, "Unknown")) &&
+       (psMapInfo && (strlen(psMapInfo->proName) == 0 || EQUAL(psMapInfo->proName, "Unknown"))) &&
+       (!psPro || psPro->proZone == 0)) )
     {
         pszProjection = CPLStrdup("");
         return CE_None;
diff --git a/frmts/jpeg2000/jpeg2000dataset.cpp b/frmts/jpeg2000/jpeg2000dataset.cpp
index 430a25e..69f46d4 100644
--- a/frmts/jpeg2000/jpeg2000dataset.cpp
+++ b/frmts/jpeg2000/jpeg2000dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jpeg2000dataset.cpp 29075 2015-04-30 12:51:21Z rouault $
+ * $Id: jpeg2000dataset.cpp 29171 2015-05-07 19:49:07Z rouault $
  *
  * Project:  JPEG-2000
  * Purpose:  Partial implementation of the ISO/IEC 15444-1 standard
@@ -35,7 +35,7 @@
 #include <jasper/jasper.h>
 #include "jpeg2000_vsil_io.h"
 
-CPL_CVSID("$Id: jpeg2000dataset.cpp 29075 2015-04-30 12:51:21Z rouault $");
+CPL_CVSID("$Id: jpeg2000dataset.cpp 29171 2015-05-07 19:49:07Z rouault $");
 
 CPL_C_START
 void    GDALRegister_JPEG2000(void);
@@ -1356,7 +1356,7 @@ void GDALRegister_JPEG2000()
         poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
         poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "JPEG-2000 part 1 (ISO/IEC 15444-1)" );
+                                   "JPEG-2000 part 1 (ISO/IEC 15444-1), based on Jasper library" );
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
                                    "frmt_jpeg2000.html" );
         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
diff --git a/frmts/netcdf/netcdfdataset.cpp b/frmts/netcdf/netcdfdataset.cpp
index 40d1cc3..faf51df 100644
--- a/frmts/netcdf/netcdfdataset.cpp
+++ b/frmts/netcdf/netcdfdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: netcdfdataset.cpp 28823 2015-03-30 14:18:13Z rouault $
+ * $Id: netcdfdataset.cpp 29200 2015-05-15 18:04:02Z rouault $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library.
@@ -33,7 +33,7 @@
 #include "cpl_error.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: netcdfdataset.cpp 28823 2015-03-30 14:18:13Z rouault $");
+CPL_CVSID("$Id: netcdfdataset.cpp 29200 2015-05-15 18:04:02Z rouault $");
 
 #include <map> //for NCDFWriteProjAttribs()
 
@@ -4638,7 +4638,8 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
             if ( papszTokens) CSLDestroy( papszTokens );
             CPLFree( pszTemp );
         }
-        if ( NCDFGetAttr( cdfid, j, "bounds", &pszTemp ) == CE_None ) { 
+        if ( NCDFGetAttr( cdfid, j, "bounds", &pszTemp ) == CE_None &&
+             pszTemp != NULL ) { 
             if ( !EQUAL( pszTemp, "" ) )
                 papszIgnoreVars = CSLAddString( papszIgnoreVars, pszTemp );
             CPLFree( pszTemp );
@@ -6871,7 +6872,7 @@ int NCDFDoesVarContainAttribVal( int nCdfId,
 
     for( int i=0; !bFound && i<CSLCount((char**)papszAttribNames); i++ ) {
         if ( NCDFGetAttr( nCdfId, nVarId, papszAttribNames[i], &pszTemp ) 
-             == CE_None ) { 
+             == CE_None && pszTemp != NULL ) { 
             if ( bStrict ) {
                 if ( EQUAL( pszTemp, papszAttribValues[i] ) )
                     bFound=TRUE;
@@ -6902,7 +6903,7 @@ int NCDFDoesVarContainAttribVal2( int nCdfId,
     if ( nVarId == -1 ) return -1;
 
     if ( NCDFGetAttr( nCdfId, nVarId, papszAttribName, &pszTemp ) 
-         != CE_None ) return FALSE;
+         != CE_None || pszTemp == NULL ) return FALSE;
 
     for( int i=0; !bFound && i<CSLCount((char**)papszAttribValues); i++ ) {
         if ( bStrict ) {
diff --git a/frmts/pcraster/pcrasterdataset.cpp b/frmts/pcraster/pcrasterdataset.cpp
index 5f37ad3..ef34e82 100644
--- a/frmts/pcraster/pcrasterdataset.cpp
+++ b/frmts/pcraster/pcrasterdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrasterdataset.cpp 28862 2015-04-07 10:10:25Z kdejong $
+ * $Id: pcrasterdataset.cpp 29187 2015-05-13 14:20:13Z kdejong $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster CSF 2.0 raster file driver
@@ -42,7 +42,7 @@
 #define INCLUDED_CPL_STRING
 #endif
 
-CPL_CVSID("$Id: pcrasterdataset.cpp 28862 2015-04-07 10:10:25Z kdejong $");
+CPL_CVSID("$Id: pcrasterdataset.cpp 29187 2015-05-13 14:20:13Z kdejong $");
 
 // PCRaster library headers.
 
@@ -330,7 +330,7 @@ PCRasterDataset::PCRasterDataset(
   CPLAssert(d_cellRepresentation != CR_UNDEFINED);
   d_valueScale = RgetValueScale(d_map);
   CPLAssert(d_valueScale != VS_UNDEFINED);
-  d_missingValue = ::missingValue(d_cellRepresentation);
+  d_defaultNoDataValue = ::missingValue(d_cellRepresentation);
   d_location_changed = false;
 
   // Create band information objects.
@@ -421,9 +421,9 @@ CSF_VS PCRasterDataset::valueScale() const
 /*!
   \return    Missing value
 */
-double PCRasterDataset::missingValue() const
+double PCRasterDataset::defaultNoDataValue() const
 {
-  return d_missingValue;
+  return d_defaultNoDataValue;
 }
 
 
diff --git a/frmts/pcraster/pcrasterdataset.h b/frmts/pcraster/pcrasterdataset.h
index 9231449..e6651d4 100644
--- a/frmts/pcraster/pcrasterdataset.h
+++ b/frmts/pcraster/pcrasterdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrasterdataset.h 28862 2015-04-07 10:10:25Z kdejong $
+ * $Id: pcrasterdataset.h 29187 2015-05-13 14:20:13Z kdejong $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster CSF 2.0 raster file driver declarations.
@@ -112,7 +112,7 @@ private:
   CSF_VS           d_valueScale;
 
   //! No data value.
-  double           d_missingValue;
+  double           d_defaultNoDataValue;
 
   bool             d_location_changed;
 
@@ -150,7 +150,7 @@ public:
 
   CSF_VS           valueScale          () const;
 
-  double           missingValue        () const;
+  double           defaultNoDataValue  () const;
 
   bool             location_changed    () const;
 
diff --git a/frmts/pcraster/pcrasterrasterband.cpp b/frmts/pcraster/pcrasterrasterband.cpp
index 74c2423..2bcf084 100644
--- a/frmts/pcraster/pcrasterrasterband.cpp
+++ b/frmts/pcraster/pcrasterrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrasterrasterband.cpp 29063 2015-04-30 07:52:46Z kdejong $
+ * $Id: pcrasterrasterband.cpp 29187 2015-05-13 14:20:13Z kdejong $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster raster band implementation.
@@ -82,7 +82,8 @@ PCRasterRasterBand::PCRasterRasterBand(
 
   : GDALPamRasterBand(),
     d_dataset(dataset),
-    d_missing_value(-FLT_MAX),
+    d_noDataValue(),
+    d_defaultNoDataValueOverridden(false),
     d_create_in(GDT_Unknown)
 
 {
@@ -111,7 +112,8 @@ double PCRasterRasterBand::GetNoDataValue(
     *success = 1;
   }
 
-  return d_dataset->missingValue();
+  return d_defaultNoDataValueOverridden
+    ? d_noDataValue : d_dataset->defaultNoDataValue();
 }
 
 
@@ -269,7 +271,7 @@ CPLErr PCRasterRasterBand::IReadBlock(
 
   // Replace in-file MV with in-app MV which may be different.
   alterFromStdMV(buffer, nrCellsRead, d_dataset->cellRepresentation(),
-         d_dataset->missingValue());
+         GetNoDataValue());
 
   return CE_None;
 }
@@ -353,25 +355,44 @@ CPLErr PCRasterRasterBand::IWriteBlock(
   memcpy(buffer, source, nr_cols * 4);
 
   // convert source no_data values to MV in dest
-  if((valuescale == VS_BOOLEAN) || (valuescale == VS_LDD)) {
-    alterToStdMV(buffer, nr_cols, CR_UINT1, d_missing_value);
-  }
-  if((valuescale == VS_SCALAR) || (valuescale == VS_DIRECTION)) {
-    alterToStdMV(buffer, nr_cols, CR_REAL4, d_missing_value);
-  }
-  if((valuescale == VS_NOMINAL)|| (valuescale == VS_ORDINAL)) {
-    alterToStdMV(buffer, nr_cols, CR_INT4, d_missing_value);
+  switch(valuescale) {
+    case VS_BOOLEAN:
+    case VS_LDD: {
+      alterToStdMV(buffer, nr_cols, CR_UINT1, GetNoDataValue());
+      break;
+    }
+    case VS_NOMINAL:
+    case VS_ORDINAL: {
+      alterToStdMV(buffer, nr_cols, CR_INT4, GetNoDataValue());
+      break;
+    }
+    case VS_SCALAR:
+    case VS_DIRECTION: {
+      alterToStdMV(buffer, nr_cols, CR_REAL4, GetNoDataValue());
+      break;
+    }
+    default: {
+      break;
+    }
   }
 
   // conversion of values according to value scale
-  if(valuescale == VS_BOOLEAN) {
-    castValuesToBooleanRange(buffer, nr_cols, CR_UINT1);
-  }
-  if(valuescale == VS_LDD) {
-    castValuesToLddRange(buffer, nr_cols);
-  }
-  if(valuescale == VS_DIRECTION) {
-    castValuesToDirectionRange(buffer, nr_cols);
+  switch(valuescale) {
+    case VS_BOOLEAN: {
+      castValuesToBooleanRange(buffer, nr_cols, CR_UINT1);
+      break;
+    }
+    case VS_LDD: {
+      castValuesToLddRange(buffer, nr_cols);
+      break;
+    }
+    case VS_DIRECTION: {
+      castValuesToDirectionRange(buffer, nr_cols);
+      break;
+    }
+    default: {
+      break;
+    }
   }
 
   RputRow(d_dataset->map(), nBlockYoff, buffer);
@@ -381,14 +402,15 @@ CPLErr PCRasterRasterBand::IWriteBlock(
 }
 
 
-CPLErr PCRasterRasterBand::SetNoDataValue(double nodata){
-  d_missing_value = nodata;
+CPLErr PCRasterRasterBand::SetNoDataValue(double nodata)
+{
+  d_noDataValue = nodata;
+  d_defaultNoDataValueOverridden = true;
 
   return CE_None;
 }
 
 
-
 //------------------------------------------------------------------------------
 // DEFINITION OF FREE OPERATORS
 //------------------------------------------------------------------------------
diff --git a/frmts/pcraster/pcrasterrasterband.h b/frmts/pcraster/pcrasterrasterband.h
index 35acc78..471e8a6 100644
--- a/frmts/pcraster/pcrasterrasterband.h
+++ b/frmts/pcraster/pcrasterrasterband.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrasterrasterband.h 28862 2015-04-07 10:10:25Z kdejong $
+ * $Id: pcrasterrasterband.h 29187 2015-05-13 14:20:13Z kdejong $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster raster band declaration.
@@ -64,7 +64,9 @@ private:
   //! Dataset this band is part of. For use only.
   PCRasterDataset const* d_dataset;
 
-  double           d_missing_value;
+  double           d_noDataValue;
+
+  bool             d_defaultNoDataValueOverridden;
 
   GDALDataType     d_create_in;
 
@@ -82,7 +84,7 @@ private:
 
 protected:
 
-  double           GetNoDataValue      (int* success);
+  double           GetNoDataValue      (int* success=NULL);
 
   double           GetMinimum          (int* success);
 
@@ -108,7 +110,7 @@ public:
 
   CPLErr           SetNoDataValue      (double no_data);
 
- //----------------------------------------------------------------------------
+  //----------------------------------------------------------------------------
   // ACCESSORS
   //----------------------------------------------------------------------------
 
diff --git a/frmts/til/tildataset.cpp b/frmts/til/tildataset.cpp
index 06bc4cf..e329e67 100644
--- a/frmts/til/tildataset.cpp
+++ b/frmts/til/tildataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tildataset.cpp 29123 2015-05-03 11:05:46Z bishop $
+ * $Id: tildataset.cpp 29198 2015-05-15 08:45:00Z rouault $
  *
  * Project:  EarthWatch .TIL Driver
  * Purpose:  Implementation of the TILDataset class.
@@ -37,7 +37,7 @@
 #include "cplkeywordparser.h"
 #include "gdal_mdreader.h"
 
-CPL_CVSID("$Id: tildataset.cpp 29123 2015-05-03 11:05:46Z bishop $");
+CPL_CVSID("$Id: tildataset.cpp 29198 2015-05-15 08:45:00Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -346,8 +346,10 @@ GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
     double      adfGeoTransform[6];
     if( poTemplateDS->GetGeoTransform( adfGeoTransform ) == CE_None )
     {
-        adfGeoTransform[0] = CPLAtof(CSLFetchNameValueDef(papszIMD,"MAP_PROJECTED_PRODUCT.ULX","0"));
-        adfGeoTransform[3] = CPLAtof(CSLFetchNameValueDef(papszIMD,"MAP_PROJECTED_PRODUCT.ULY","0"));
+        // According to https://www.digitalglobe.com/sites/default/files/ISD_External.pdf, ulx=originX and 
+        // is "Easting of the center of the upper left pixel of the image."
+        adfGeoTransform[0] = CPLAtof(CSLFetchNameValueDef(papszIMD,"MAP_PROJECTED_PRODUCT.ULX","0")) - adfGeoTransform[1] / 2;
+        adfGeoTransform[3] = CPLAtof(CSLFetchNameValueDef(papszIMD,"MAP_PROJECTED_PRODUCT.ULY","0")) - adfGeoTransform[5] / 2;
         poDS->SetGeoTransform(adfGeoTransform);
     }
 
diff --git a/frmts/vrt/vrtdataset.cpp b/frmts/vrt/vrtdataset.cpp
index 338bc94..48beb5d 100644
--- a/frmts/vrt/vrtdataset.cpp
+++ b/frmts/vrt/vrtdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtdataset.cpp 29038 2015-04-28 09:03:36Z rouault $
+ * $Id: vrtdataset.cpp 29192 2015-05-14 10:07:42Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTDataset
@@ -33,7 +33,7 @@
 #include "cpl_minixml.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: vrtdataset.cpp 29038 2015-04-28 09:03:36Z rouault $");
+CPL_CVSID("$Id: vrtdataset.cpp 29192 2015-05-14 10:07:42Z rouault $");
 
 /************************************************************************/
 /*                            VRTDataset()                             */
@@ -1199,9 +1199,15 @@ int VRTDataset::CheckCompatibleForDatasetIO()
                 VRTSimpleSource* poSource = (VRTSimpleSource* )papoSources[iSource];
                 if (!EQUAL(poSource->GetType(), "SimpleSource"))
                     return FALSE;
-                if (poSource->GetBand() == NULL)
+
+                GDALRasterBand *srcband = poSource->GetBand();
+                if (srcband == NULL)
+                    return FALSE;
+                if (srcband->GetDataset() == NULL)
+                    return FALSE;
+                if (srcband->GetDataset()->GetRasterCount() <= iBand)
                     return FALSE;
-                if (poSource->GetBand()->GetBand() != iBand + 1)
+                if (srcband->GetDataset()->GetRasterBand(iBand + 1) != srcband)
                     return FALSE;
                 osResampling = poSource->GetResampling();
             }
@@ -1220,9 +1226,15 @@ int VRTDataset::CheckCompatibleForDatasetIO()
                     return FALSE;
                 if (!poSource->IsSameExceptBandNumber(poRefSource))
                     return FALSE;
-                if (poSource->GetBand() == NULL)
+
+                GDALRasterBand *srcband = poSource->GetBand();
+                if (srcband == NULL)
+                    return FALSE;
+                if (srcband->GetDataset() == NULL)
+                    return FALSE;
+                if (srcband->GetDataset()->GetRasterCount() <= iBand)
                     return FALSE;
-                if (poSource->GetBand()->GetBand() != iBand + 1)
+                if (srcband->GetDataset()->GetRasterBand(iBand + 1) != srcband)
                     return FALSE;
                 if (osResampling.compare(poSource->GetResampling()) != 0)
                     return FALSE;
diff --git a/frmts/vrt/vrtsourcedrasterband.cpp b/frmts/vrt/vrtsourcedrasterband.cpp
index aadf366..1c8e5a9 100644
--- a/frmts/vrt/vrtsourcedrasterband.cpp
+++ b/frmts/vrt/vrtsourcedrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtsourcedrasterband.cpp 28899 2015-04-14 09:27:00Z rouault $
+ * $Id: vrtsourcedrasterband.cpp 29161 2015-05-06 10:18:19Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTSourcedRasterBand
@@ -32,7 +32,7 @@
 #include "cpl_minixml.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: vrtsourcedrasterband.cpp 28899 2015-04-14 09:27:00Z rouault $");
+CPL_CVSID("$Id: vrtsourcedrasterband.cpp 29161 2015-05-06 10:18:19Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -206,11 +206,13 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     for( iSource = 0; eErr == CE_None && iSource < nSources; iSource++ )
     {
         psExtraArg->pfnProgress = GDALScaledProgress;
-            psExtraArg->pProgressData = 
+        psExtraArg->pProgressData = 
                 GDALCreateScaledProgress( 1.0 * iSource / nSources,
                                         1.0 * (iSource + 1) / nSources,
                                         pfnProgressGlobal,
                                         pProgressDataGlobal );
+        if( psExtraArg->pProgressData == NULL )
+            psExtraArg->pfnProgress = NULL;
 
         eErr = 
             papoSources[iSource]->RasterIO( nXOff, nYOff, nXSize, nYSize, 
diff --git a/frmts/vrt/vrtsources.cpp b/frmts/vrt/vrtsources.cpp
index a6980d3..3ad8af2 100644
--- a/frmts/vrt/vrtsources.cpp
+++ b/frmts/vrt/vrtsources.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtsources.cpp 28979 2015-04-23 10:25:51Z rouault $
+ * $Id: vrtsources.cpp 29204 2015-05-16 21:49:02Z 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 28979 2015-04-23 10:25:51Z rouault $");
+CPL_CVSID("$Id: vrtsources.cpp 29204 2015-05-16 21:49:02Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -836,12 +836,22 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
         *pnReqXSize = poRasterBand->GetXSize() - *pnReqXOff;
         bModifiedX = TRUE;
     }
+    if( *pdfReqXOff + *pdfReqXSize > poRasterBand->GetXSize() )
+    {
+        *pdfReqXSize = poRasterBand->GetXSize() - *pdfReqXOff;
+        bModifiedX = TRUE;
+    }
 
     if( *pnReqYOff + *pnReqYSize > poRasterBand->GetYSize() )
     {
         *pnReqYSize = poRasterBand->GetYSize() - *pnReqYOff;
         bModifiedY = TRUE;
     }
+    if( *pdfReqYOff + *pdfReqYSize > poRasterBand->GetYSize() )
+    {
+        *pdfReqYSize = poRasterBand->GetYSize() - *pdfReqYOff;
+        bModifiedY = TRUE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Don't do anything if the requesting region is completely off    */
@@ -915,15 +925,13 @@ VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                            GDALDataType eBufType, 
                            GSpacing nPixelSpace,
                            GSpacing nLineSpace,
-                           GDALRasterIOExtraArg* psExtraArg )
+                           GDALRasterIOExtraArg* psExtraArgIn )
 
 {
     GDALRasterIOExtraArg sExtraArg;
-    if( psExtraArg == NULL )
-    {
-        INIT_RASTERIO_EXTRA_ARG(sExtraArg);
-        psExtraArg = &sExtraArg;
-    }
+
+    INIT_RASTERIO_EXTRA_ARG(sExtraArg);
+    GDALRasterIOExtraArg* psExtraArg = &sExtraArg;
 
     // The window we will actually request from the source raster band.
     double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
@@ -946,11 +954,14 @@ VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
     CPLErr eErr;
 
-    GDALRIOResampleAlg     eResampleAlgBack = psExtraArg->eResampleAlg;
     if( osResampling.size() )
     {
         psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(osResampling);
     }
+    else if( psExtraArgIn != NULL )
+    {
+        psExtraArg->eResampleAlg = psExtraArgIn->eResampleAlg;
+    }
     psExtraArg->bFloatingPointWindowValidity = TRUE;
     psExtraArg->dfXOff = dfReqXOff;
     psExtraArg->dfYOff = dfReqYOff;
@@ -966,10 +977,6 @@ VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                                 nOutXSize, nOutYSize, 
                                 eBufType, nPixelSpace, nLineSpace, psExtraArg );
 
-    if( osResampling.size() )
-        psExtraArg->eResampleAlg = eResampleAlgBack;
-    psExtraArg->bFloatingPointWindowValidity = FALSE;
-
     return eErr;
 }
 
@@ -1139,7 +1146,7 @@ CPLErr VRTSimpleSource::DatasetRasterIO(
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg)
+                               GDALRasterIOExtraArg* psExtraArgIn)
 {
     if (!EQUAL(GetType(), "SimpleSource"))
     {
@@ -1148,6 +1155,11 @@ CPLErr VRTSimpleSource::DatasetRasterIO(
         return CE_Failure;
     }
 
+    GDALRasterIOExtraArg sExtraArg;
+
+    INIT_RASTERIO_EXTRA_ARG(sExtraArg);
+    GDALRasterIOExtraArg* psExtraArg = &sExtraArg;
+
     // The window we will actually request from the source raster band.
     double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
@@ -1168,11 +1180,14 @@ CPLErr VRTSimpleSource::DatasetRasterIO(
     if (poDS == NULL)
         return CE_Failure;
 
-    GDALRIOResampleAlg     eResampleAlgBack = psExtraArg->eResampleAlg;
     if( osResampling.size() )
     {
         psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(osResampling);
     }
+    else if( psExtraArgIn != NULL )
+    {
+        psExtraArg->eResampleAlg = psExtraArgIn->eResampleAlg;
+    }
     psExtraArg->bFloatingPointWindowValidity = TRUE;
     psExtraArg->dfXOff = dfReqXOff;
     psExtraArg->dfYOff = dfReqYOff;
@@ -1187,9 +1202,6 @@ CPLErr VRTSimpleSource::DatasetRasterIO(
                            nOutXSize, nOutYSize,
                            eBufType, nBandCount, panBandMap,
                            nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
-    if( osResampling.size() )
-        psExtraArg->eResampleAlg = eResampleAlgBack;
-    psExtraArg->bFloatingPointWindowValidity = FALSE;
 
     return eErr;
 }
@@ -1245,15 +1257,13 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                            GDALDataType eBufType, 
                            GSpacing nPixelSpace,
                            GSpacing nLineSpace,
-                           GDALRasterIOExtraArg* psExtraArg )
+                           GDALRasterIOExtraArg* psExtraArgIn )
 
 {
     GDALRasterIOExtraArg sExtraArg;
-    if( psExtraArg == NULL )
-    {
-        INIT_RASTERIO_EXTRA_ARG(sExtraArg);
-        psExtraArg = &sExtraArg;
-    }
+
+    INIT_RASTERIO_EXTRA_ARG(sExtraArg);
+    GDALRasterIOExtraArg* psExtraArg = &sExtraArg;
 
     // The window we will actually request from the source raster band.
     double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
@@ -1287,11 +1297,15 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
     CPLErr eErr;
 
-    GDALRIOResampleAlg     eResampleAlgBack = psExtraArg->eResampleAlg;
     if( osResampling.size() )
     {
         psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(osResampling);
     }
+    else if( psExtraArgIn != NULL )
+    {
+        psExtraArg->eResampleAlg = psExtraArgIn->eResampleAlg;
+    }
+
     psExtraArg->bFloatingPointWindowValidity = TRUE;
     psExtraArg->dfXOff = dfReqXOff;
     psExtraArg->dfYOff = dfReqYOff;
@@ -1303,10 +1317,6 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                                    pafSrc, nReqXSize, nReqYSize, GDT_Float32, 
                                    0, 0, psExtraArg );
 
-    if( osResampling.size() )
-        psExtraArg->eResampleAlg = eResampleAlgBack;
-    psExtraArg->bFloatingPointWindowValidity = FALSE;
-
     if( eErr != CE_None )
     {
         VSIFree( pafSrc );
@@ -1799,15 +1809,13 @@ VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                             GDALDataType eBufType, 
                             GSpacing nPixelSpace,
                             GSpacing nLineSpace,
-                            GDALRasterIOExtraArg* psExtraArg)
+                            GDALRasterIOExtraArg* psExtraArgIn)
     
 {
     GDALRasterIOExtraArg sExtraArg;
-    if( psExtraArg == NULL )
-    {
-        INIT_RASTERIO_EXTRA_ARG(sExtraArg);
-        psExtraArg = &sExtraArg;
-    }
+
+    INIT_RASTERIO_EXTRA_ARG(sExtraArg);
+    GDALRasterIOExtraArg* psExtraArg = &sExtraArg;
 
     // The window we will actually request from the source raster band.
     double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
@@ -1822,11 +1830,14 @@ VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
         return CE_None;
 
-    GDALRIOResampleAlg     eResampleAlgBack = psExtraArg->eResampleAlg;
     if( osResampling.size() )
     {
         psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(osResampling);
     }
+    else if( psExtraArgIn != NULL )
+    {
+        psExtraArg->eResampleAlg = psExtraArgIn->eResampleAlg;
+    }
     psExtraArg->bFloatingPointWindowValidity = TRUE;
     psExtraArg->dfXOff = dfReqXOff;
     psExtraArg->dfYOff = dfReqYOff;
@@ -1841,10 +1852,6 @@ VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                        eBufType,
                        nPixelSpace, nLineSpace, psExtraArg );
 
-    if( osResampling.size() )
-        psExtraArg->eResampleAlg = eResampleAlgBack;
-    psExtraArg->bFloatingPointWindowValidity = FALSE;
-
     return eErr;
 }
 
diff --git a/frmts/wms/frmt_wms.html b/frmts/wms/frmt_wms.html
index 757c2d4..12b2a72 100644
--- a/frmts/wms/frmt_wms.html
+++ b/frmts/wms/frmt_wms.html
@@ -145,7 +145,7 @@
 		</tr>
 		<tr>
 			<td class="xml">    <BandsCount><span class="value">3</span></BandsCount></td>
-			<td class="desc">Number of bands/channels, 1 for grayscale data, 3 for RGB. (optional, defaults to 3)</td>
+			<td class="desc">Number of bands/channels, 1 for grayscale data, 3 for RGB, 4 for RGBA. (optional, defaults to 3)</td>
 		</tr>
         <tr>
             <td class="xml">    <DataType><span class="value">Byte</span></DataType></td>
@@ -510,6 +510,21 @@ A list of subdatasets will be returned, resulting from the parsing of the GetTil
 </p></li>
 </ul>
 
+<h2>Generation of WMS service description XML file</h2>
+
+The WMS service description XML file can be generated manually, or created
+as the output of the CreateCopy() operation of the WMS driver, only if the source
+dataset is itself a WMS dataset. Said otherwise, you can use gdal_translate
+with as source dataset any of the above syntax mentioned in "Open syntax" and
+as output an XML file.
+
+For example:
+<pre>
+gdal_translate "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer?f=json" wms.xml -of WMS
+</pre>
+
+The generated file will come with default values that you may need to edit.
+
 <h2>See Also:</h2>
 
 <ul>
diff --git a/gcore/GNUmakefile b/gcore/GNUmakefile
index c9ef0fa..9c0c4bc 100644
--- a/gcore/GNUmakefile
+++ b/gcore/GNUmakefile
@@ -25,7 +25,7 @@ XTRA_OPT 	:=	$(XTRA_OPT) -DRENAME_INTERNAL_LIBTIFF_SYMBOLS
 endif
 endif
 
-CPPFLAGS	:=	 -I../frmts/gtiff -I../frmts/mem -I../frmts/vrt -I../ogr -I../ogr/ogrsf_frmts/generic $(JSON_INCLUDE) $(CPPFLAGS) $(PAM_SETTING) $(XTRA_OPT)
+CPPFLAGS	:=	 -I../frmts/gtiff -I../frmts/mem -I../frmts/vrt -I../ogr -I../ogr/ogrsf_frmts/generic $(JSON_INCLUDE) -I../ogr/ogrsf_frmts/geojson $(CPPFLAGS) $(PAM_SETTING) $(XTRA_OPT)
 
 ifeq ($(HAVE_SQLITE),yes)
 CXXFLAGS :=	$(CXXFLAGS) -DSQLITE_ENABLED
diff --git a/gcore/gdal.h b/gcore/gdal.h
index 68eb13f..a32146a 100644
--- a/gcore/gdal.h
+++ b/gcore/gdal.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal.h 29123 2015-05-03 11:05:46Z bishop $
+ * $Id: gdal.h 29243 2015-05-24 15:53:26Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  GDAL Core C/Public declarations.
@@ -989,6 +989,9 @@ void CPL_DLL CPL_STDCALL GDALRATDumpReadable( GDALRasterAttributeTableH,
 GDALRasterAttributeTableH CPL_DLL CPL_STDCALL 
     GDALRATClone( GDALRasterAttributeTableH );
 
+void CPL_DLL* CPL_STDCALL 
+    GDALRATSerializeJSON( GDALRasterAttributeTableH );
+
 int CPL_DLL CPL_STDCALL GDALRATGetRowOfValue( GDALRasterAttributeTableH , double );
 
 
diff --git a/gcore/gdal_mdreader.cpp b/gcore/gdal_mdreader.cpp
index 8e4f143..8f1ef56 100644
--- a/gcore/gdal_mdreader.cpp
+++ b/gcore/gdal_mdreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_mdreader.cpp 29143 2015-05-03 20:49:53Z rouault $
+ * $Id: gdal_mdreader.cpp 29190 2015-05-13 21:40:30Z bishop $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata (mainly the remote sensing imagery) from files of 
@@ -42,8 +42,13 @@
 #include "mdreader/reader_pleiades.h"
 #include "mdreader/reader_rdk1.h"
 #include "mdreader/reader_landsat.h"
+#include "mdreader/reader_spot.h"
+#include "mdreader/reader_rapid_eye.h"
+#include "mdreader/reader_alos.h"
+#include "mdreader/reader_eros.h"
+#include "mdreader/reader_kompsat.h"
 
-CPL_CVSID("$Id: gdal_mdreader.cpp 29143 2015-05-03 20:49:53Z rouault $");
+CPL_CVSID("$Id: gdal_mdreader.cpp 29190 2015-05-13 21:40:30Z bishop $");
 
 /**
  * The RPC parameters names
@@ -117,25 +122,50 @@ GDALMDReaderBase* GDALMDReaderManager::GetReader(const char *pszPath,
         INIT_READER(GDALMDReaderOrbView);
     }
 
-    // required filename.tif filename_rpc.txt (filename_metadata.txt optional)
     if(nType & MDR_GE)
     {
         INIT_READER(GDALMDReaderGeoEye);
     }
 
+    if(nType & MDR_LS)
+    {
+        INIT_READER(GDALMDReaderLandsat);
+    }
+
     if(nType & MDR_PLEIADES)
     {
         INIT_READER(GDALMDReaderPleiades);
     }
 
+    if(nType & MDR_SPOT)
+    {
+        INIT_READER(GDALMDReaderSpot);
+    }
+
     if(nType & MDR_RDK1)
     {
         INIT_READER(GDALMDReaderResursDK1);
     }
 
-    if(nType & MDR_LS)
+    if(nType & MDR_RE)
     {
-        INIT_READER(GDALMDReaderLandsat);
+        INIT_READER(GDALMDReaderRapidEye);
+    }
+
+    // required filename.tif filename.rpc filename.txt
+    if(nType & MDR_KOMPSAT)
+    {
+        INIT_READER(GDALMDReaderKompsat);
+    }
+
+    if(nType & MDR_EROS)
+    {
+        INIT_READER(GDALMDReaderEROS);
+    }
+
+    if(nType & MDR_ALOS)
+    {
+        INIT_READER(GDALMDReaderALOS);
     }
 
     return NULL;
@@ -193,7 +223,7 @@ void GDALMDReaderBase::LoadMetadata()
 }
 
 /**
- * GetAcqisitionTimeFromString1()
+ * GetAcqisitionTimeFromString()
  */
 const time_t GDALMDReaderBase::GetAcquisitionTimeFromString(
         const char* pszDateTime)
@@ -272,7 +302,7 @@ char** GDALMDReaderBase::ReadXMLToList(CPLXMLNode* psNode, char** papszList,
 
     if (psNode->eType == CXT_Text)
     {
-        return AddXMLNameValueToList(papszList, pszName, psNode->pszValue);
+        papszList = AddXMLNameValueToList(papszList, pszName, psNode->pszValue);
     }
 
     if (psNode->eType == CXT_Element)
@@ -280,28 +310,27 @@ char** GDALMDReaderBase::ReadXMLToList(CPLXMLNode* psNode, char** papszList,
 
         int nAddIndex = 0;
         bool bReset = false;
-        const char* pszLastNodeName = NULL;
         for(CPLXMLNode* psChildNode = psNode->psChild; NULL != psChildNode;
             psChildNode = psChildNode->psNext)
         {
             if (psChildNode->eType == CXT_Element)
             {
-                if(bReset)
-                {
-                    bReset = false;
-                    nAddIndex = 0;
-                }
                 // check name duplicates
-                if(NULL != psChildNode->psNext && psChildNode->psNext->eType == CXT_Element)
+                if(NULL != psChildNode->psNext)
                 {
+                    if(bReset)
+                    {
+                        bReset = false;
+                        nAddIndex = 0;
+                    }
+
                     if(EQUAL(psChildNode->pszValue, psChildNode->psNext->pszValue))
                     {
                         nAddIndex++;
-                        pszLastNodeName = psChildNode->pszValue;
                     }
                     else
                     { // the name changed
-                        pszLastNodeName = NULL;
+
                         if(nAddIndex > 0)
                         {
                             bReset = true;
@@ -309,9 +338,18 @@ char** GDALMDReaderBase::ReadXMLToList(CPLXMLNode* psNode, char** papszList,
                         }
                     }
                 }
-                else if( pszLastNodeName && EQUAL(psChildNode->pszValue, pszLastNodeName) )
+                else
                 {
-                    nAddIndex++;
+                    if(bReset)
+                    {
+                        bReset = false;
+                        nAddIndex = 0;
+                    }
+
+                    if(nAddIndex > 0)
+                    {
+                        nAddIndex++;
+                    }
                 }
 
                 char szName[512];
@@ -356,13 +394,13 @@ char** GDALMDReaderBase::ReadXMLToList(CPLXMLNode* psNode, char** papszList,
                 }
             }
         }
+    }
 
-        // proceed next only on top level
+    // proceed next only on top level
 
-        if(NULL != psNode->psNext && EQUAL(pszName, ""))
-        {
-             papszList = ReadXMLToList(psNode->psNext, papszList, pszName);
-        }
+    if(NULL != psNode->psNext && EQUAL(pszName, ""))
+    {
+         papszList = ReadXMLToList(psNode->psNext, papszList, pszName);
     }
 
     return papszList;
@@ -566,7 +604,7 @@ char ** GDALLoadRPCFile( const CPLString& soFilePath )
         }
         else
         {
-            while( *pszRPBVal == ' ' ) pszRPBVal ++;
+            while( *pszRPBVal == ' ' || *pszRPBVal == '\t' ) pszRPBVal ++;
             papszMD = CSLSetNameValue( papszMD, apszRPBMap[i], pszRPBVal );
         }
     }
@@ -592,7 +630,7 @@ char ** GDALLoadRPCFile( const CPLString& soFilePath )
             }
             else
             {
-                while( *pszRPBVal == ' ' ) pszRPBVal ++;
+                while( *pszRPBVal == ' ' || *pszRPBVal == '\t' ) pszRPBVal ++;
                 soVal += pszRPBVal;
                 soVal += " ";
             }
diff --git a/gcore/gdal_mdreader.h b/gcore/gdal_mdreader.h
index 9e7937d..f060cae 100644
--- a/gcore/gdal_mdreader.h
+++ b/gcore/gdal_mdreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_mdreader.h 29138 2015-05-03 19:12:48Z rouault $
+ * $Id: gdal_mdreader.h 29190 2015-05-13 21:40:30Z bishop $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata (mainly the remote sensing imagery) from files of 
@@ -46,7 +46,7 @@
 #define MD_NAME_MDTYPE      "METADATATYPE"         /**< Metadata reader type property name. The reader processed this metadata */
 
 #define MD_DATETIMEFORMAT "%Y-%m-%d %H:%M:%S"      /**< Date time format */
-#define MD_CLOUDCOVER_NA "999"               /**< The value if cloud cover n/a*/
+#define MD_CLOUDCOVER_NA "999"           /**< The value if cloud cover is n/a */
 
 /**
  * RPC/RPB specific defines
@@ -72,15 +72,20 @@
  */
 
 typedef enum {
-    MDR_None     = 0x000000,    /**< no reader */
-    MDR_DG       = 0x000001,    /**< Digital Globe, METADATATYPE=DG */
-    MDR_GE       = 0x000002,    /**< Geo Eye,       METADATATYPE=GE */
-    MDR_OV       = 0x000004,    /**< Orb View,      METADATATYPE=OV */
-    MDR_PLEIADES = 0x000008,    /**< Pleiades,      METADATATYPE=DIMAP */
-    MDR_RDK1     = 0x000010,    /**< Resurs DK1,    METADATATYPE=MSP */
-    MDR_LS       = 0x000020,    /**< Landsat,       METADATATYPE=ODL */
-    MDR_ANY  = MDR_DG | MDR_GE | MDR_OV | MDR_PLEIADES | MDR_RDK1 |
-               MDR_LS /**< any reader */
+    MDR_None     = 0x00000000,    /**< no reader */
+    MDR_DG       = 0x00000001,    /**< Digital Globe, METADATATYPE=DG */
+    MDR_GE       = 0x00000002,    /**< Geo Eye,       METADATATYPE=GE */
+    MDR_OV       = 0x00000004,    /**< Orb View,      METADATATYPE=OV */
+    MDR_PLEIADES = 0x00000008,    /**< Pleiades,      METADATATYPE=DIMAP */
+    MDR_SPOT     = 0x00000010,    /**< Spot,          METADATATYPE=DIMAP */
+    MDR_RDK1     = 0x00000020,    /**< Resurs DK1,    METADATATYPE=MSP */
+    MDR_LS       = 0x00000040,    /**< Landsat,       METADATATYPE=ODL */
+    MDR_RE       = 0x00000080,    /**< RapidEye,      METADATATYPE=RE */
+    MDR_KOMPSAT  = 0x00000100,    /**< Kompsat,       METADATATYPE=KARI */
+    MDR_EROS     = 0x00000200,    /**< EROS,          METADATATYPE=EROS */
+    MDR_ALOS     = 0x00000400,    /**< ALOS,          METADATATYPE=ALOS */
+    MDR_ANY  = MDR_DG | MDR_GE | MDR_OV | MDR_PLEIADES | MDR_SPOT | MDR_RDK1 |
+               MDR_LS | MDR_RE | MDR_KOMPSAT | MDR_EROS | MDR_ALOS /**< any reader */
 } MDReaders;
 
 
@@ -146,7 +151,7 @@ protected:
      * @param papszList A list to fill with name=value strings
      * @param pszName A name to add
      * @param pszValue A value to add
-     * @return
+     * @return An input list filled with values
      */
     virtual char** AddXMLNameValueToList(char** papszList, const char *pszName,
                                          const char *pszValue);
diff --git a/gcore/gdal_rat.cpp b/gcore/gdal_rat.cpp
index 37d6201..a5830d6 100644
--- a/gcore/gdal_rat.cpp
+++ b/gcore/gdal_rat.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rat.cpp 28016 2014-11-26 15:13:41Z rouault $
+ * $Id: gdal_rat.cpp 29243 2015-05-24 15:53:26Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALRasterAttributeTable and related classes.
@@ -30,8 +30,10 @@
 
 #include "gdal_priv.h"
 #include "gdal_rat.h"
+#include "json.h"
+#include "ogrgeojsonwriter.h"
 
-CPL_CVSID("$Id: gdal_rat.cpp 28016 2014-11-26 15:13:41Z rouault $");
+CPL_CVSID("$Id: gdal_rat.cpp 29243 2015-05-24 15:53:26Z rouault $");
 
 /**
  * \class GDALRasterAttributeTable
@@ -592,6 +594,99 @@ CPLXMLNode *GDALRasterAttributeTable::Serialize() const
 }
 
 /************************************************************************/
+/*                             SerializeJSON()                              */
+/************************************************************************/
+
+void *GDALRasterAttributeTable::SerializeJSON() const
+
+{
+    json_object *poRAT = json_object_new_object();
+
+    if( ( GetColumnCount() == 0 ) && ( GetRowCount() == 0 ) ) 
+        return poRAT;
+
+
+/* -------------------------------------------------------------------- */
+/*      Add attributes with regular binning info if appropriate.        */
+/* -------------------------------------------------------------------- */
+    double dfRow0Min, dfBinSize;
+    json_object *poRow0Min, *poBinSize;
+
+    if( GetLinearBinning(&dfRow0Min, &dfBinSize) )
+    {
+        poRow0Min = json_object_new_double_with_precision( dfRow0Min, 16 );
+        json_object_object_add( poRAT, "row0Min", poRow0Min );
+
+        poBinSize = json_object_new_double_with_precision( dfBinSize, 16 );
+        json_object_object_add( poRAT, "binSize", poBinSize );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Define each column.                                             */
+/* -------------------------------------------------------------------- */
+    int iCol;
+    int iColCount = GetColumnCount();
+    json_object *poFieldDefnArray = json_object_new_array();
+    json_object *poFieldDefn, *poColumnIndex, *poName, *poType, *poUsage;
+
+    for( iCol = 0; iCol < iColCount; iCol++ )
+    {
+        poFieldDefn = json_object_new_object();
+
+        poColumnIndex = json_object_new_int( iCol );
+        json_object_object_add( poFieldDefn, "index", poColumnIndex );
+
+        poName = json_object_new_string( GetNameOfCol(iCol) );
+        json_object_object_add( poFieldDefn, "name", poName );
+
+        poType = json_object_new_int( (int) GetTypeOfCol(iCol) );
+        json_object_object_add( poFieldDefn, "type", poType );
+
+        poUsage = json_object_new_int( (int) GetUsageOfCol(iCol) );
+        json_object_object_add( poFieldDefn, "usage", poUsage );
+
+        json_object_array_add( poFieldDefnArray, poFieldDefn );
+    }
+
+    json_object_object_add( poRAT, "fieldDefn", poFieldDefnArray );
+
+/* -------------------------------------------------------------------- */
+/*      Write out each row.                                             */
+/* -------------------------------------------------------------------- */
+    int iRow;
+    int iRowCount = GetRowCount();
+    json_object *poRowArray = json_object_new_array();
+    json_object *poRow, *poRowIndex, *poFArray, *poF;
+
+    for( iRow = 0; iRow < iRowCount; iRow++ )
+    {
+        poRow = json_object_new_object();
+
+        poRowIndex = json_object_new_int(iRow);
+        json_object_object_add( poRow, "index", poRowIndex );
+
+        poFArray = json_object_new_array();
+
+        for( iCol = 0; iCol < iColCount; iCol++ )
+        {
+            if( GetTypeOfCol(iCol) == GFT_Integer )
+                poF = json_object_new_int( GetValueAsInt(iRow, iCol) );
+            else if( GetTypeOfCol(iCol) == GFT_Real )
+                poF = json_object_new_double_with_precision( GetValueAsDouble(iRow, iCol), 16 );
+            else
+                poF = json_object_new_string( GetValueAsString(iRow, iCol) );
+
+            json_object_array_add( poFArray, poF );
+        }
+        json_object_object_add( poRow, "f", poFArray );
+        json_object_array_add( poRowArray, poRow );
+    }
+    json_object_object_add( poRAT, "row", poRowArray );
+
+    return poRAT;
+}
+
+/************************************************************************/
 /*                              XMLInit()                               */
 /************************************************************************/
 
@@ -1818,3 +1913,21 @@ GDALRATClone( GDALRasterAttributeTableH hRAT )
 
     return ((GDALRasterAttributeTable *) hRAT)->Clone();
 }
+
+/************************************************************************/
+/*                            GDALRATSerializeJSON()                    */
+/************************************************************************/
+
+/**
+ * \brief Serialize Raster Attribute Table in Json format
+ *
+ * This function is the same as the C++ method GDALRasterAttributeTable::SerializeJSON()
+ */
+void* CPL_STDCALL 
+GDALRATSerializeJSON( GDALRasterAttributeTableH hRAT )
+
+{
+    VALIDATE_POINTER1( hRAT, "GDALRATSerializeJSON", NULL );
+
+    return ((GDALRasterAttributeTable *) hRAT)->SerializeJSON();
+}
diff --git a/gcore/gdal_rat.h b/gcore/gdal_rat.h
index f36939d..a70445d 100644
--- a/gcore/gdal_rat.h
+++ b/gcore/gdal_rat.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rat.h 26117 2013-06-29 20:22:34Z rouault $
+ * $Id: gdal_rat.h 29243 2015-05-24 15:53:26Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  GDALRasterAttributeTable class declarations.
@@ -254,6 +254,7 @@ public:
      * (GetRowCount() * GetColCount() > RAT_MAX_ELEM_FOR_CLONE)
      */
     virtual CPLXMLNode   *Serialize() const;
+    virtual void   *SerializeJSON() const;
     virtual CPLErr        XMLInit( CPLXMLNode *, const char * );
 
     virtual CPLErr        InitializeFromColorTable( const GDALColorTable * );
diff --git a/gcore/gdal_version.h b/gcore/gdal_version.h
index b6bc902..fbae6a9 100644
--- a/gcore/gdal_version.h
+++ b/gcore/gdal_version.h
@@ -22,8 +22,8 @@
 #endif
 
 #ifndef GDAL_RELEASE_DATE
-#  define GDAL_RELEASE_DATE     20150504
+#  define GDAL_RELEASE_DATE     20150525
 #endif
 #ifndef GDAL_RELEASE_NAME
-#  define GDAL_RELEASE_NAME     "2.0.0beta1"
+#  define GDAL_RELEASE_NAME     "2.0.0beta2"
 #endif
diff --git a/gcore/gdaldataset.cpp b/gcore/gdaldataset.cpp
index 60cd1ce..5c78fca 100644
--- a/gcore/gdaldataset.cpp
+++ b/gcore/gdaldataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldataset.cpp 29097 2015-05-01 20:13:36Z rouault $
+ * $Id: gdaldataset.cpp 29161 2015-05-06 10:18:19Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Base class for raster file formats.  
@@ -46,7 +46,7 @@
 
 #include <map>
 
-CPL_CVSID("$Id: gdaldataset.cpp 29097 2015-05-01 20:13:36Z rouault $");
+CPL_CVSID("$Id: gdaldataset.cpp 29161 2015-05-06 10:18:19Z rouault $");
 
 CPL_C_START
 GDALAsyncReader *
@@ -1527,19 +1527,25 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
 
         pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
 
-        psExtraArg->pfnProgress = GDALScaledProgress;
-        psExtraArg->pProgressData = 
-            GDALCreateScaledProgress( 1.0 * iBandIndex / nBandCount,
-                                      1.0 * (iBandIndex + 1) / nBandCount,
-                                      pfnProgressGlobal,
-                                      pProgressDataGlobal );
+        if( nBandCount > 1 )
+        {
+            psExtraArg->pfnProgress = GDALScaledProgress;
+            psExtraArg->pProgressData = 
+                GDALCreateScaledProgress( 1.0 * iBandIndex / nBandCount,
+                                        1.0 * (iBandIndex + 1) / nBandCount,
+                                        pfnProgressGlobal,
+                                        pProgressDataGlobal );
+            if( psExtraArg->pProgressData == NULL )
+                psExtraArg->pfnProgress = NULL;
+        }
 
         eErr = poBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
                                   (void *) pabyBandData, nBufXSize, nBufYSize,
                                   eBufType, nPixelSpace, nLineSpace,
                                   psExtraArg );
 
-        GDALDestroyScaledProgress( psExtraArg->pProgressData );
+        if( nBandCount > 1 )
+            GDALDestroyScaledProgress( psExtraArg->pProgressData );
     }
     
     psExtraArg->pfnProgress = pfnProgressGlobal;
diff --git a/gcore/gdaldriver.cpp b/gcore/gdaldriver.cpp
index b795c96..5b60d51 100644
--- a/gcore/gdaldriver.cpp
+++ b/gcore/gdaldriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldriver.cpp 29077 2015-04-30 13:23:31Z rouault $
+ * $Id: gdaldriver.cpp 29207 2015-05-18 17:23:45Z mloskot $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALDriver class (and C wrappers)
@@ -31,7 +31,7 @@
 #include "gdal_priv.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: gdaldriver.cpp 29077 2015-04-30 13:23:31Z rouault $");
+CPL_CVSID("$Id: gdaldriver.cpp 29207 2015-05-18 17:23:45Z mloskot $");
 
 CPL_C_START
 const char* GDALClientDatasetGetFilename(const char* pszFilename);
@@ -86,9 +86,8 @@ GDALDriver::~GDALDriver()
 void CPL_STDCALL GDALDestroyDriver( GDALDriverH hDriver )
 
 {
-    VALIDATE_POINTER0( hDriver, "GDALDestroyDriver" );
-
-    delete ((GDALDriver *) hDriver);
+    if( hDriver != NULL )
+        delete ((GDALDriver *) hDriver);
 }
 
 /************************************************************************/
diff --git a/gcore/gdaljp2metadata.cpp b/gcore/gdaljp2metadata.cpp
index 9bde12d..6ebbe9c 100644
--- a/gcore/gdaljp2metadata.cpp
+++ b/gcore/gdaljp2metadata.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaljp2metadata.cpp 29082 2015-04-30 17:03:52Z rouault $
+ * $Id: gdaljp2metadata.cpp 29210 2015-05-19 19:04:28Z rouault $
  *
  * Project:  GDAL 
  * Purpose:  GDALJP2Metadata - Read GeoTIFF and/or GML georef info.
@@ -40,7 +40,7 @@
 #include "json.h"
 #include "gdaljp2metadatagenerator.h"
 
-CPL_CVSID("$Id: gdaljp2metadata.cpp 29082 2015-04-30 17:03:52Z rouault $");
+CPL_CVSID("$Id: gdaljp2metadata.cpp 29210 2015-05-19 19:04:28Z rouault $");
 
 static const unsigned char msi_uuid2[16] =
 {0xb1,0x4b,0xf8,0xbd,0x08,0x3d,0x4b,0x43,
@@ -991,11 +991,10 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
 /* -------------------------------------------------------------------- */
     int bNeedAxisFlip = FALSE;
 
+    OGRSpatialReference oSRS;
     if( bSuccess && pszSRSName != NULL 
         && (pszProjection == NULL || strlen(pszProjection) == 0) )
     {
-        OGRSpatialReference oSRS;
-
         if( EQUALN(pszSRSName,"epsg:",5) )
         {
             if( oSRS.SetFromUserInput( pszSRSName ) == OGRERR_NONE )
@@ -1033,9 +1032,6 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
                   "Got projection from GML box: %s", 
                  pszProjection );
 
-    CPLDestroyXMLNode( psXML );
-    psXML = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Do we need to flip the axes?                                    */
 /* -------------------------------------------------------------------- */
@@ -1046,6 +1042,60 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
         bNeedAxisFlip = FALSE;
         CPLDebug( "GMLJP2", "Suppressed axis flipping based on GDAL_IGNORE_AXIS_ORIENTATION." );
     }
+    
+    if( pszSRSName && bNeedAxisFlip )
+    {
+        // Suppress explicit axis order in SRS definition
+
+        OGR_SRSNode *poGEOGCS = oSRS.GetAttrNode( "GEOGCS" );
+        if( poGEOGCS != NULL )
+            poGEOGCS->StripNodes( "AXIS" );
+
+        OGR_SRSNode *poPROJCS = oSRS.GetAttrNode( "PROJCS" );
+        if (poPROJCS != NULL && oSRS.EPSGTreatsAsNorthingEasting())
+            poPROJCS->StripNodes( "AXIS" );
+        
+        CPLFree(pszProjection);
+        oSRS.exportToWkt( &pszProjection );
+
+    }
+    
+    /* Some Pleiades files have explicit <gml:axisName>Easting</gml:axisName> */
+    /* <gml:axisName>Northing</gml:axisName> to override default EPSG order */
+    if( bNeedAxisFlip && psRG != NULL )
+    {
+        int nAxisCount = 0;
+        int bFirstAxisIsEastOrLong = FALSE, bSecondAxisIsNorthOrLat = FALSE;
+        for(CPLXMLNode* psIter = psRG->psChild; psIter != NULL; psIter = psIter->psNext )
+        {
+            if( psIter->eType == CXT_Element && strcmp(psIter->pszValue, "axisName") == 0 &&
+                psIter->psChild != NULL && psIter->psChild->eType == CXT_Text )
+            {
+                if( nAxisCount == 0 && 
+                    (EQUALN(psIter->psChild->pszValue, "EAST", 4) ||
+                     EQUALN(psIter->psChild->pszValue, "LONG", 4) ) )
+                {
+                    bFirstAxisIsEastOrLong = TRUE;
+                }
+                else if( nAxisCount == 1 &&
+                         (EQUALN(psIter->psChild->pszValue, "NORTH", 5) ||
+                          EQUALN(psIter->psChild->pszValue, "LAT", 3)) )
+                {
+                    bSecondAxisIsNorthOrLat = TRUE;
+                }
+                nAxisCount ++;
+            }
+        }
+        if( bFirstAxisIsEastOrLong && bSecondAxisIsNorthOrLat )
+        {
+            CPLDebug( "GMLJP2", "Disable axis flip because of explicit axisName disabling it" );
+            bNeedAxisFlip = FALSE;
+        }
+    }
+
+    CPLDestroyXMLNode( psXML );
+    psXML = NULL;
+    psRG = NULL;
 
     if( bNeedAxisFlip )
     {
@@ -1190,7 +1240,8 @@ int GDALJP2Metadata::GetGMLJP2GeoreferencingInfo( int& nEPSGCode,
                                                   double adfXVector[2],
                                                   double adfYVector[2],
                                                   const char*& pszComment,
-                                                  CPLString& osDictBox )
+                                                  CPLString& osDictBox,
+                                                  int& bNeedAxisFlip )
 {
 
 /* -------------------------------------------------------------------- */
@@ -1199,7 +1250,7 @@ int GDALJP2Metadata::GetGMLJP2GeoreferencingInfo( int& nEPSGCode,
     OGRSpatialReference oSRS;
     char *pszWKTCopy = (char *) pszProjection;
     nEPSGCode = 0;
-    int  bNeedAxisFlip = FALSE;
+    bNeedAxisFlip = FALSE;
 
     if( oSRS.importFromWkt( &pszWKTCopy ) != OGRERR_NONE )
         return FALSE;
@@ -1395,9 +1446,10 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )
     double adfYVector[2];
     const char* pszComment = "";
     CPLString osDictBox;
+    int bNeedAxisFlip = FALSE;
     if( !GetGMLJP2GeoreferencingInfo( nEPSGCode, adfOrigin,
                                       adfXVector, adfYVector,
-                                      pszComment, osDictBox ) )
+                                      pszComment, osDictBox, bNeedAxisFlip ) )
     {
         return NULL;
     }
@@ -1409,6 +1461,30 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )
         strcpy( szSRSName, 
                 "gmljp2://xml/CRSDictionary.gml#ogrcrs1" );
 
+    // Compute bounding box
+    double dfX1 = adfGeoTransform[0];
+    double dfX2 = adfGeoTransform[0] + nXSize * adfGeoTransform[1];
+    double dfX3 = adfGeoTransform[0] +                               nYSize * adfGeoTransform[2];
+    double dfX4 = adfGeoTransform[0] + nXSize * adfGeoTransform[1] + nYSize * adfGeoTransform[2];
+    double dfY1 = adfGeoTransform[3];
+    double dfY2 = adfGeoTransform[3] + nXSize * adfGeoTransform[4];
+    double dfY3 = adfGeoTransform[3] +                               nYSize * adfGeoTransform[5];
+    double dfY4 = adfGeoTransform[3] + nXSize * adfGeoTransform[4] + nYSize * adfGeoTransform[5];
+    double dfLCX = MIN(MIN(dfX1,dfX2),MIN(dfX3,dfX4));
+    double dfLCY = MIN(MIN(dfY1,dfY2),MIN(dfY3,dfY4));
+    double dfUCX = MAX(MAX(dfX1,dfX2),MAX(dfX3,dfX4));
+    double dfUCY = MAX(MAX(dfY1,dfY2),MAX(dfY3,dfY4));
+    if( bNeedAxisFlip )
+    {
+        double dfTmp = dfLCX;
+        dfLCX = dfLCY;
+        dfLCY = dfTmp;
+        
+        dfTmp = dfUCX;
+        dfUCX = dfUCY;
+        dfUCY = dfTmp;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      For now we hardcode for a minimal instance format.              */
 /* -------------------------------------------------------------------- */
@@ -1420,7 +1496,10 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )
 "   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
 "   xsi:schemaLocation=\"http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/profiles/gmlJP2Profile/1.0.0/gmlJP2Profile.xsd\">\n"
 "  <gml:boundedBy>\n"
-"    <gml:Null>withheld</gml:Null>\n"
+"    <gml:Envelope srsName=\"%s\">\n"
+"      <gml:lowerCorner>%.15g %.15g</gml:lowerCorner>\n"
+"      <gml:upperCorner>%.15g %.15g</gml:upperCorner>\n"
+"    </gml:Envelope>\n"
 "  </gml:boundedBy>\n"
 "  <gml:featureMember>\n"
 "    <gml:FeatureCollection>\n"
@@ -1458,6 +1537,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )
 "    </gml:FeatureCollection>\n"
 "  </gml:featureMember>\n"
 "</gml:FeatureCollection>\n",
+             szSRSName, dfLCX, dfLCY, dfUCX, dfUCY,
              nXSize-1, nYSize-1, szSRSName, adfOrigin[0], adfOrigin[1],
              pszComment,
              szSRSName, adfXVector[0], adfXVector[1], 
@@ -2147,9 +2227,10 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
         double adfXVector[2];
         double adfYVector[2];
         const char* pszComment = "";   
+        int bNeedAxisFlip = FALSE;
         if( !GetGMLJP2GeoreferencingInfo( nEPSGCode, adfOrigin,
                                         adfXVector, adfYVector,
-                                        pszComment, osDictBox ) )
+                                        pszComment, osDictBox, bNeedAxisFlip ) )
         {
             return NULL;
         }
diff --git a/gcore/gdaljp2metadata.h b/gcore/gdaljp2metadata.h
index e0ff390..2a40e9d 100644
--- a/gcore/gdaljp2metadata.h
+++ b/gcore/gdaljp2metadata.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaljp2metadata.h 29054 2015-04-29 19:31:41Z rouault $
+ * $Id: gdaljp2metadata.h 29210 2015-05-19 19:04:28Z rouault $
  *
  * Project:  GDAL 
  * Purpose:  JP2 Box Reader (and GMLJP2 Interpreter)
@@ -132,7 +132,8 @@ private:
                                           double adfXVector[2],
                                           double adfYVector[2],
                                           const char*& pszComment,
-                                          CPLString& osDictBox );
+                                          CPLString& osDictBox,
+                                          int& bNeedAxisFlip );
     static CPLXMLNode* CreateGDALMultiDomainMetadataXML(
                                        GDALDataset* poSrcDS,
                                        int bMainMDDomainOnly );
diff --git a/gcore/makefile.vc b/gcore/makefile.vc
index 711b5cd..a70bb7b 100644
--- a/gcore/makefile.vc
+++ b/gcore/makefile.vc
@@ -20,7 +20,7 @@ GDAL_ROOT	=	..
 
 !INCLUDE ..\nmake.opt
 
-EXTRAFLAGS =	$(PAM_SETTING) -I..\frmts\gtiff -I..\frmts\mem -I..\frmts\vrt -I..\ogr\ogrsf_frmts\generic -I..\ogr\ogrsf_frmts\geojson\libjson $(SQLITEDEF)
+EXTRAFLAGS =	$(PAM_SETTING) -I..\frmts\gtiff -I..\frmts\mem -I..\frmts\vrt -I..\ogr\ogrsf_frmts\generic -I../ogr/ogrsf_frmts/geojson -I..\ogr\ogrsf_frmts\geojson\libjson $(SQLITEDEF)
 
 !IFDEF SQLITE_LIB
 SQLITEDEF	=	-DSQLITE_ENABLED
diff --git a/gcore/mdreader/GNUmakefile b/gcore/mdreader/GNUmakefile
index 4061015..0bcd040 100644
--- a/gcore/mdreader/GNUmakefile
+++ b/gcore/mdreader/GNUmakefile
@@ -2,7 +2,9 @@
 include ../../GDALmake.opt
 
 OBJ	=	reader_digital_globe.o reader_geo_eye.o reader_orb_view.o \
-                reader_pleiades.o reader_rdk1.o reader_landsat.o
+                reader_pleiades.o reader_rdk1.o reader_landsat.o \
+                reader_spot.o reader_rapid_eye.o reader_alos.o reader_eros.o \
+                reader_kompsat.o
 
 UP_OBJ   = $(addprefix ../,$(OBJ))
 
diff --git a/gcore/mdreader/makefile.vc b/gcore/mdreader/makefile.vc
index a9c054d..76d69d5 100644
--- a/gcore/mdreader/makefile.vc
+++ b/gcore/mdreader/makefile.vc
@@ -1,6 +1,10 @@
 OBJ	=	reader_digital_globe.obj reader_geo_eye.obj reader_orb_view.obj \
-                reader_pleiades.obj reader_rdk1.obj reader_landsat.obj
+                reader_pleiades.obj reader_rdk1.obj reader_landsat.obj \
+                reader_spot.obj reader_rapid_eye.obj reader_alos.obj \
+                reader_eros.obj reader_kompsat.obj
 
+GDAL_ROOT	=	..\..
+                
 !INCLUDE ..\..\nmake.opt
 
 EXTRAFLAGS =	-I..\..\port -I..\..\ogr -I..\
@@ -9,4 +13,4 @@ default:	$(OBJ)
     xcopy /D  /Y *.obj ..\
 
 clean:
-	-del *.obj *.res
+	-del *.obj
diff --git a/gcore/mdreader/reader_alos.cpp b/gcore/mdreader/reader_alos.cpp
new file mode 100644
index 0000000..6456f2b
--- /dev/null
+++ b/gcore/mdreader/reader_alos.cpp
@@ -0,0 +1,405 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL Core
+ * Purpose:  Read metadata from Alos imagery.
+ * Author:   Alexander Lisovenko
+ * Author:   Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014-2015 NextGIS <info at nextgis.ru>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "reader_alos.h"
+
+/**
+ * GDALMDReaderALOS()
+ */
+GDALMDReaderALOS::GDALMDReaderALOS(const char *pszPath,
+        char **papszSiblingFiles) : GDALMDReaderBase(pszPath, papszSiblingFiles)
+{
+    CPLString osDirName = CPLGetDirname(pszPath);
+    CPLString osBaseName = CPLGetBasename(pszPath);
+
+    const char* pszIMDSourceFilename = CPLFormFilename(osDirName, "summary", ".txt");
+    if (CPLCheckForFile((char*)pszIMDSourceFilename, papszSiblingFiles))
+    {
+        m_osIMDSourceFilename = pszIMDSourceFilename;
+    }
+    else
+    {
+        pszIMDSourceFilename = CPLFormFilename( osDirName, "SUMMARY", ".TXT");
+        if (CPLCheckForFile((char*)pszIMDSourceFilename, papszSiblingFiles))
+        {
+            m_osIMDSourceFilename = pszIMDSourceFilename;
+        }
+    }
+
+    const char *pszHDRFileName;
+    if( osBaseName.size() >= 6 )
+    {
+        // check if this is separate band or whole image
+        // test without 6 symbols
+        pszHDRFileName = CPLFormFilename(osDirName, CPLSPrintf("HDR%s",
+                                                    osBaseName + 6), "txt");
+        if (CPLCheckForFile((char*)pszHDRFileName, papszSiblingFiles))
+        {
+            m_osHDRSourceFilename = pszHDRFileName;
+        }
+        else
+        {
+            pszHDRFileName = CPLFormFilename(osDirName, CPLSPrintf("HDR%s",
+                                            osBaseName + 6), "TXT");
+            if (CPLCheckForFile((char*)pszHDRFileName, papszSiblingFiles))
+            {
+                m_osHDRSourceFilename = pszHDRFileName;
+            }
+        }
+    }
+
+    // test without 3 symbols
+    if( osBaseName.size() >= 3 && m_osHDRSourceFilename.empty())
+    {
+        pszHDRFileName = CPLFormFilename(osDirName, CPLSPrintf("HDR%s",
+                                         osBaseName + 3), "txt");
+        if (CPLCheckForFile((char*)pszHDRFileName, papszSiblingFiles))
+        {
+            m_osHDRSourceFilename = pszHDRFileName;
+        }
+        else
+        {
+            pszHDRFileName = CPLFormFilename(osDirName, CPLSPrintf("HDR%s",
+                                             osBaseName + 3), "TXT");
+            if (CPLCheckForFile((char*)pszHDRFileName, papszSiblingFiles))
+            {
+                m_osHDRSourceFilename = pszHDRFileName;
+            }
+        }
+    }
+
+    // test without 6 symbols
+    const char *pszRPCFileName;
+    if( osBaseName.size() >= 6 )
+    {
+        pszRPCFileName = CPLFormFilename(osDirName, CPLSPrintf("RPC%s",
+                                                    osBaseName + 6), "txt");
+        if (CPLCheckForFile((char*)pszRPCFileName, papszSiblingFiles))
+        {
+            m_osRPBSourceFilename = pszRPCFileName;
+        }
+        else
+        {
+            pszRPCFileName = CPLFormFilename(osDirName, CPLSPrintf("RPC%s",
+                                            osBaseName + 6), "TXT");
+            if (CPLCheckForFile((char*)pszRPCFileName, papszSiblingFiles))
+            {
+                m_osRPBSourceFilename = pszRPCFileName;
+            }
+        }
+    }
+
+    // test without 3 symbols
+    if( osBaseName.size() >= 3 && m_osRPBSourceFilename.empty())
+    {
+        pszRPCFileName = CPLFormFilename(osDirName, CPLSPrintf("RPC%s",
+                                         osBaseName + 3), "txt");
+        if (CPLCheckForFile((char*)pszRPCFileName, papszSiblingFiles))
+        {
+            m_osRPBSourceFilename = pszRPCFileName;
+        }
+        else
+        {
+            pszRPCFileName = CPLFormFilename(osDirName, CPLSPrintf("RPC%s",
+                                             osBaseName + 3), "TXT");
+            if (CPLCheckForFile((char*)pszRPCFileName, papszSiblingFiles))
+            {
+                m_osRPBSourceFilename = pszRPCFileName;
+            }
+        }
+    }
+
+    if(m_osIMDSourceFilename.size())
+        CPLDebug( "MDReaderALOS", "IMD Filename: %s",
+              m_osIMDSourceFilename.c_str() );
+    if(m_osHDRSourceFilename.size())
+        CPLDebug( "MDReaderALOS", "HDR Filename: %s",
+              m_osHDRSourceFilename.c_str() );
+    if(m_osRPBSourceFilename.size())
+        CPLDebug( "MDReaderALOS", "RPB Filename: %s",
+              m_osRPBSourceFilename.c_str() );
+}
+
+/**
+ * ~GDALMDReaderALOS()
+ */
+GDALMDReaderALOS::~GDALMDReaderALOS()
+{
+}
+
+/**
+ * HasRequiredFiles()
+ */
+const bool GDALMDReaderALOS::HasRequiredFiles() const
+{
+    if (!m_osIMDSourceFilename.empty())
+        return true;
+
+    if(!m_osHDRSourceFilename.empty() && !m_osRPBSourceFilename.empty())
+        return true;
+
+    return false;
+}
+
+/**
+ * GetMetadataFiles()
+ */
+char** GDALMDReaderALOS::GetMetadataFiles() const
+{
+    char **papszFileList = NULL;
+    if(!m_osIMDSourceFilename.empty())
+        papszFileList= CSLAddString( papszFileList, m_osIMDSourceFilename );
+    if(!m_osHDRSourceFilename.empty())
+        papszFileList= CSLAddString( papszFileList, m_osHDRSourceFilename );
+    if(!m_osRPBSourceFilename.empty())
+        papszFileList= CSLAddString( papszFileList, m_osRPBSourceFilename );
+
+    return papszFileList;
+}
+
+/**
+ * LoadMetadata()
+ */
+void GDALMDReaderALOS::LoadMetadata()
+{
+    if(m_bIsMetadataLoad)
+        return;
+
+    if(!m_osIMDSourceFilename.empty())
+    {
+        m_papszIMDMD = CSLLoad(m_osIMDSourceFilename);
+    }
+
+    if(!m_osHDRSourceFilename.empty())
+    {
+        if(NULL == m_papszIMDMD)
+        {
+            m_papszIMDMD = CSLLoad(m_osHDRSourceFilename);
+        }
+        else
+        {
+            char** papszHDR = CSLLoad(m_osHDRSourceFilename);
+            m_papszIMDMD = CSLMerge(m_papszIMDMD, papszHDR);
+            CSLDestroy(papszHDR);
+        }
+    }
+
+    m_papszRPCMD = LoadRPCTxtFile();
+
+    m_papszDEFAULTMD = CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "ALOS");
+
+    m_bIsMetadataLoad = true;
+
+    const char* pszSatId1 = CSLFetchNameValue(m_papszIMDMD, "Lbi_Satellite");
+    const char* pszSatId2 = CSLFetchNameValue(m_papszIMDMD, "Lbi_Sensor");
+    if(NULL != pszSatId1 && NULL != pszSatId2)
+    {
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                           MD_NAME_SATELLITE, CPLSPrintf( "%s %s",
+                           CPLStripQuotes(pszSatId1).c_str(),
+                           CPLStripQuotes(pszSatId2).c_str()));
+    }
+    else if(NULL != pszSatId1 && NULL == pszSatId2)
+    {
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                MD_NAME_SATELLITE, CPLStripQuotes(pszSatId1));
+    }
+    else if(NULL == pszSatId1 && NULL != pszSatId2)
+    {
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                MD_NAME_SATELLITE, CPLStripQuotes(pszSatId2));
+    }
+
+
+    const char* pszCloudCover = CSLFetchNameValue(m_papszIMDMD,
+                                                 "Img_CloudQuantityOfAllImage");
+    if(NULL != pszCloudCover)
+    {
+        int nCC = atoi(pszCloudCover);
+        if(nCC >= 99)
+        {
+            m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_CLOUDCOVER,
+                                               MD_CLOUDCOVER_NA);
+        }
+        else
+        {
+            m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                          MD_NAME_CLOUDCOVER, CPLSPrintf("%d", nCC * 10));
+        }
+    }
+
+    const char* pszDate = CSLFetchNameValue(m_papszIMDMD,
+                                                     "Img_SceneCenterDateTime");
+
+    if(NULL != pszDate)
+    {
+        char buffer[80];
+        time_t timeMid = GetAcquisitionTimeFromString(CPLStripQuotes(pszDate));
+        strftime (buffer, 80, MD_DATETIMEFORMAT, localtime(&timeMid));
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                           MD_NAME_ACQDATETIME, buffer);
+    }
+    else
+    {
+        pszDate = CSLFetchNameValue(m_papszIMDMD, "Lbi_ObservationDate");
+        if(NULL != pszDate)
+        {
+            const char* pszTime = "00:00:00.000";
+
+            char buffer[80];
+            time_t timeMid = GetAcquisitionTimeFromString(CPLSPrintf( "%s %s",
+                                              CPLStripQuotes(pszDate).c_str(),
+                                              CPLStripQuotes(pszTime).c_str()));
+            strftime (buffer, 80, MD_DATETIMEFORMAT, localtime(&timeMid));
+            m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                               MD_NAME_ACQDATETIME, buffer);
+        }
+    }
+}
+
+static const char *apszRPCTXT20ValItems[] =
+{
+    RPC_LINE_NUM_COEFF,
+    RPC_LINE_DEN_COEFF,
+    RPC_SAMP_NUM_COEFF,
+    RPC_SAMP_DEN_COEFF,
+    NULL
+};
+
+/**
+ * LoadRPCTxtFile
+ */
+char** GDALMDReaderALOS::LoadRPCTxtFile()
+{
+    if(m_osRPBSourceFilename.empty())
+        return NULL;
+
+    char** papszLines = CSLLoad(m_osRPBSourceFilename);
+    if(NULL == papszLines)
+        return NULL;
+
+    const char* pszFirstRow = papszLines[0];
+    char** papszRPB = NULL;
+    if(NULL != pszFirstRow)
+    {
+        char buff[50] = {0};
+        int nOffset = 0;
+        CPLStrlcpy(buff, pszFirstRow + nOffset, 7);
+        nOffset += 6;
+        papszRPB = CSLAddNameValue(papszRPB, RPC_LINE_OFF, buff);
+
+        CPLStrlcpy(buff, pszFirstRow + nOffset, 6);
+        nOffset += 5;
+        papszRPB = CSLAddNameValue(papszRPB, RPC_SAMP_OFF, buff);
+
+        CPLStrlcpy(buff, pszFirstRow + nOffset, 9);
+        nOffset += 8;
+        papszRPB = CSLAddNameValue(papszRPB, RPC_LAT_OFF, buff);
+
+        CPLStrlcpy(buff, pszFirstRow + nOffset, 10);
+        nOffset += 9;
+        papszRPB = CSLAddNameValue(papszRPB, RPC_LONG_OFF, buff);
+
+        CPLStrlcpy(buff, pszFirstRow + nOffset, 6);
+        nOffset += 5;
+        papszRPB = CSLAddNameValue(papszRPB, RPC_HEIGHT_OFF, buff);
+
+        CPLStrlcpy(buff, pszFirstRow + nOffset, 7);
+        nOffset += 6;
+        papszRPB = CSLAddNameValue(papszRPB, RPC_LINE_SCALE, buff);
+
+        CPLStrlcpy(buff, pszFirstRow + nOffset, 6);
+        nOffset += 5;
+        papszRPB = CSLAddNameValue(papszRPB, RPC_SAMP_SCALE, buff);
+
+        CPLStrlcpy(buff, pszFirstRow + nOffset, 9);
+        nOffset += 8;
+        papszRPB = CSLAddNameValue(papszRPB, RPC_LAT_SCALE, buff);
+
+        CPLStrlcpy(buff, pszFirstRow + nOffset, 10);
+        nOffset += 9;
+        papszRPB = CSLAddNameValue(papszRPB, RPC_LONG_SCALE, buff);
+
+        CPLStrlcpy(buff, pszFirstRow + nOffset, 6);
+        nOffset += 5;
+        papszRPB = CSLAddNameValue(papszRPB, RPC_HEIGHT_SCALE, buff);
+
+        int i, j;
+        for( i = 0; apszRPCTXT20ValItems[i] != NULL; i++ )
+        {
+            CPLString value;
+            for( j = 1; j < 21; j++ )
+            {
+                CPLStrlcpy(buff, pszFirstRow + nOffset, 13);
+                nOffset += 12;
+
+                value = value + " " + CPLString(buff);
+            }
+            papszRPB = CSLAddNameValue(papszRPB, apszRPCTXT20ValItems[i], value);
+        }
+    }
+    CSLDestroy(papszLines);
+
+    return papszRPB;
+}
+
+/**
+ * GetAcqisitionTimeFromString()
+ */
+const time_t GDALMDReaderALOS::GetAcquisitionTimeFromString(
+        const char* pszDateTime)
+{
+    if(NULL == pszDateTime)
+        return 0;
+
+    int iYear;
+    int iMonth;
+    int iDay;
+    int iHours;
+    int iMin;
+    int iSec;
+
+    int r = sscanf ( pszDateTime, "%4d%2d%2d %d:%d:%d.%*d",
+                     &iYear, &iMonth, &iDay, &iHours, &iMin, &iSec);
+
+    if (r != 6)
+        return 0;
+
+    struct tm tmDateTime;
+    tmDateTime.tm_sec = iSec;
+    tmDateTime.tm_min = iMin;
+    tmDateTime.tm_hour = iHours;
+    tmDateTime.tm_mday = iDay;
+    tmDateTime.tm_mon = iMonth - 1;
+    tmDateTime.tm_year = iYear - 1900;
+    tmDateTime.tm_isdst = -1;
+
+    return mktime(&tmDateTime);
+}
diff --git a/gcore/mdreader/reader_geo_eye.h b/gcore/mdreader/reader_alos.h
similarity index 66%
copy from gcore/mdreader/reader_geo_eye.h
copy to gcore/mdreader/reader_alos.h
index d2644f5..4eefb51 100644
--- a/gcore/mdreader/reader_geo_eye.h
+++ b/gcore/mdreader/reader_alos.h
@@ -1,13 +1,13 @@
 /******************************************************************************
- * $Id: reader_geo_eye.h 29138 2015-05-03 19:12:48Z rouault $
+ * $Id$
  *
  * Project:  GDAL Core
- * Purpose:  Read metadata from GeoEye imagery.
+ * Purpose:  Read metadata from Alos imagery.
  * Author:   Alexander Lisovenko
  * Author:   Dmitry Baryshnikov, polimax at mail.ru
  *
  ******************************************************************************
- * Copyright (c) 2014-2015, NextGIS info at nextgis.ru
+ * Copyright (c) 2014-2015 NextGIS <info at nextgis.ru>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -27,41 +27,43 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
- 
-#ifndef READER_GEO_EYE_H_INCLUDED
-#define READER_GEO_EYE_H_INCLUDED
 
-#include "../gdal_mdreader.h"
+#ifndef READER_ALOS_H_INCLUDED
+#define READER_ALOS_H_INCLUDED
+
+#include "reader_pleiades.h"
 
 /**
- at brief Metadata reader for Geo Eye
+Metadata reader for ALOS
 
-TIFF filename:        aaaaaaaaaa.tif
-Metadata filename:    *_metadata*
-RPC filename:         aaaaaaaaaa_rpc.txt
+TIFF filename:      IMG-sssssssssssssss-pppppppp.tif or
+                    IMG-01-sssssssssssssss-pppppppp.tif
+                    IMG-02-sssssssssssssss-pppppppp.tif
+Metadata filename:  summary.txt
+RPC filename:       RPC-sssssssssssssss-pppppppp.txt
 
 Common metadata (from metadata filename):
-    MDName_SatelliteId:            Sensor
-    MDName_CloudCover:             Percent Cloud Cover
-    MDName_AcquisitionDateTime:    Acquisition Date/Time
-
+    AcquisitionDateTime: Img_SceneCenterDateTime or Lbi_ObservationDate
+    SatelliteId:         Lbi_Satellite
+    CloudCover:          Img_CloudQuantityOfAllImage
 */
 
-class GDALMDReaderGeoEye: public GDALMDReaderBase
+class GDALMDReaderALOS: public GDALMDReaderBase
 {
 public:
-    GDALMDReaderGeoEye(const char *pszPath, char **papszSiblingFiles);
-    virtual ~GDALMDReaderGeoEye();
+    GDALMDReaderALOS(const char *pszPath, char **papszSiblingFiles);
+    virtual ~GDALMDReaderALOS();
     virtual const bool HasRequiredFiles() const;
     virtual char** GetMetadataFiles() const;
 protected:
     virtual void LoadMetadata();
+    char** LoadRPCTxtFile();
     virtual const time_t GetAcquisitionTimeFromString(const char* pszDateTime);
-    char **LoadRPCWktFile() const;
-    char **LoadIMDWktFile() const;
 protected:
     CPLString m_osIMDSourceFilename;
+    CPLString m_osHDRSourceFilename;
     CPLString m_osRPBSourceFilename;
 };
 
-#endif // READER_GEO_EYE_H_INCLUDED
+#endif // READER_ALOS_H_INCLUDED
+
diff --git a/gcore/mdreader/reader_digital_globe.h b/gcore/mdreader/reader_digital_globe.h
index 5fd0ae3..3cdd6b0 100644
--- a/gcore/mdreader/reader_digital_globe.h
+++ b/gcore/mdreader/reader_digital_globe.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_digital_globe.h 29138 2015-05-03 19:12:48Z rouault $
+ * $Id: reader_digital_globe.h 29190 2015-05-13 21:40:30Z bishop $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from DigitalGlobe imagery.
@@ -36,21 +36,21 @@
 /**
 @brief Metadata reader for DigitalGlobe
 
-TIFF filename:        aaaaaaaaaa.tif
-Metadata filename:    aaaaaaaaaa.IMD
-RPC filename:         aaaaaaaaaa.RPB
+TIFF filename:      aaaaaaaaaa.tif
+Metadata filename:  aaaaaaaaaa.IMD
+RPC filename:       aaaaaaaaaa.RPB
 
 Common metadata (from metadata filename):
-    MDName_SatelliteId:            satId    
-    MDName_CloudCover:             cloudCover
-    MDName_AcquisitionDateTime:    earliestAcqTime, latestAcqTime
+    SatelliteId:         satId
+    CloudCover:          cloudCover
+    AcquisitionDateTime: earliestAcqTime, latestAcqTime
 
 OR
 Metadata and RPC filename:    aaaaaaaaaa.XML
 Common metadata (from metadata filename):
-    MDName_SatelliteId:            SATID    
-    MDName_CloudCover:             CLOUDCOVER
-    MDName_AcquisitionDateTime:    EARLIESTACQTIME, LATESTACQTIME
+    SatelliteId:         SATID
+    CloudCover:          CLOUDCOVER
+    AcquisitionDateTime: EARLIESTACQTIME, LATESTACQTIME
 
 */
 
diff --git a/gcore/mdreader/reader_eros.cpp b/gcore/mdreader/reader_eros.cpp
new file mode 100644
index 0000000..af7680a
--- /dev/null
+++ b/gcore/mdreader/reader_eros.cpp
@@ -0,0 +1,286 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL Core
+ * Purpose:  Read metadata from EROS imagery.
+ * Author:   Alexander Lisovenko
+ * Author:   Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014-2015, NextGIS info at nextgis.ru
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "reader_eros.h"
+
+/**
+ * GDALMDReaderEROS()
+ */
+GDALMDReaderEROS::GDALMDReaderEROS(const char *pszPath,
+        char **papszSiblingFiles) : GDALMDReaderBase(pszPath, papszSiblingFiles)
+{
+    CPLString osBaseName = CPLGetBasename(pszPath);
+    CPLString osDirName = CPLGetDirname(pszPath);
+    char szMetadataName[512] = {0};
+    const char* pszPassFileName;
+    size_t i;
+    if( osBaseName.size() > 511 )
+        return;
+    for(i = 0; i < osBaseName.size(); i++)
+    {
+        if(EQUALN(osBaseName + i, ".", 1))
+        {
+            pszPassFileName = CPLFormFilename( osDirName, szMetadataName,
+                                               "pass" );
+            if (CPLCheckForFile((char*)pszPassFileName, papszSiblingFiles))
+            {
+                m_osIMDSourceFilename = pszPassFileName;
+                break;
+            }
+            else
+            {
+                pszPassFileName = CPLFormFilename( osDirName, szMetadataName,
+                                                   "PASS" );
+                if (CPLCheckForFile((char*)pszPassFileName, papszSiblingFiles))
+                {
+                    m_osIMDSourceFilename = pszPassFileName;
+                    break;
+                }
+            }
+        }
+        szMetadataName[i] = osBaseName[i];
+    }
+
+    if(m_osIMDSourceFilename.empty())
+    {
+        pszPassFileName = CPLFormFilename( osDirName, szMetadataName, "pass" );
+        if (CPLCheckForFile((char*)pszPassFileName, papszSiblingFiles))
+        {
+            m_osIMDSourceFilename = pszPassFileName;
+        }
+        else
+        {
+            pszPassFileName = CPLFormFilename( osDirName, szMetadataName, "PASS" );
+            if (CPLCheckForFile((char*)pszPassFileName, papszSiblingFiles))
+            {
+                m_osIMDSourceFilename = pszPassFileName;
+            }
+        }
+    }
+
+    const char* pszRPCFileName = CPLFormFilename( osDirName, szMetadataName,
+                                                  "rpc" );
+    if (CPLCheckForFile((char*)pszRPCFileName, papszSiblingFiles))
+    {
+        m_osRPBSourceFilename = pszRPCFileName;
+    }
+    else
+    {
+        pszRPCFileName = CPLFormFilename( osDirName, szMetadataName, "RPC" );
+        if (CPLCheckForFile((char*)pszRPCFileName, papszSiblingFiles))
+        {
+            m_osRPBSourceFilename = pszRPCFileName;
+        }
+    }
+
+    if(m_osIMDSourceFilename.size())
+        CPLDebug( "MDReaderEROS", "IMD Filename: %s",
+              m_osIMDSourceFilename.c_str() );
+    if(m_osRPBSourceFilename.size())
+        CPLDebug( "MDReaderEROS", "RPB Filename: %s",
+              m_osRPBSourceFilename.c_str() );
+}
+
+/**
+ * ~GDALMDReaderEROS()
+ */
+GDALMDReaderEROS::~GDALMDReaderEROS()
+{
+}
+
+/**
+ * HasRequiredFiles()
+ */
+const bool GDALMDReaderEROS::HasRequiredFiles() const
+{
+    if (!m_osIMDSourceFilename.empty())
+        return true;
+    if (!m_osRPBSourceFilename.empty())
+        return true;
+
+    return false;
+}
+
+/**
+ * GetMetadataFiles()
+ */
+char** GDALMDReaderEROS::GetMetadataFiles() const
+{
+    char **papszFileList = NULL;
+    if(!m_osIMDSourceFilename.empty())
+        papszFileList= CSLAddString( papszFileList, m_osIMDSourceFilename );
+    if(!m_osRPBSourceFilename.empty())
+        papszFileList = CSLAddString( papszFileList, m_osRPBSourceFilename );
+    return papszFileList;
+}
+
+/**
+ * LoadMetadata()
+ */
+void GDALMDReaderEROS::LoadMetadata()
+{
+    if(m_bIsMetadataLoad)
+        return;
+
+    if(!m_osIMDSourceFilename.empty())
+    {
+        m_papszIMDMD = LoadImdTxtFile();
+    }
+
+    if(!m_osRPBSourceFilename.empty())
+    {
+        m_papszRPCMD = GDALLoadRPCFile( m_osRPBSourceFilename );
+    }
+
+    m_papszDEFAULTMD = CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "EROS");
+
+    m_bIsMetadataLoad = true;
+
+    const char* pszSatId1 = CSLFetchNameValue(m_papszIMDMD, "satellite");
+    const char* pszSatId2 = CSLFetchNameValue(m_papszIMDMD, "camera");
+    if(NULL != pszSatId1 && NULL != pszSatId2)
+    {
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                           MD_NAME_SATELLITE, CPLSPrintf( "%s %s",
+                           CPLStripQuotes(pszSatId1).c_str(),
+                           CPLStripQuotes(pszSatId2).c_str()));
+    }
+    else if(NULL != pszSatId1 && NULL == pszSatId2)
+    {
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                MD_NAME_SATELLITE, CPLStripQuotes(pszSatId1));
+    }
+    else if(NULL == pszSatId1 && NULL != pszSatId2)
+    {
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                MD_NAME_SATELLITE, CPLStripQuotes(pszSatId2));
+    }
+
+    const char* pszCloudCover = CSLFetchNameValue(m_papszIMDMD,
+                                                 "overall_cc");
+    if(NULL != pszCloudCover)
+    {
+        int nCC = atoi(pszCloudCover);
+        if(nCC > 100 || nCC < 0)
+        {
+            m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_CLOUDCOVER,
+                                               MD_CLOUDCOVER_NA);
+        }
+        else
+        {
+            m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                          MD_NAME_CLOUDCOVER, CPLSPrintf("%d", nCC));
+        }
+    }
+
+    const char* pszDate = CSLFetchNameValue(m_papszIMDMD, "sweep_start_utc");
+    if(NULL != pszDate)
+    {
+        char buffer[80];
+        time_t timeMid = GetAcquisitionTimeFromString(CPLStripQuotes(pszDate));
+        strftime (buffer, 80, MD_DATETIMEFORMAT, localtime(&timeMid));
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                           MD_NAME_ACQDATETIME, buffer);
+    }
+
+}
+
+/**
+ * LoadImdTxtFile
+ */
+char** GDALMDReaderEROS::LoadImdTxtFile()
+{
+    char** papszLines = CSLLoad(m_osIMDSourceFilename);
+    if(NULL == papszLines)
+        return NULL;
+
+    char** papszIMD = NULL;
+    char szName[22];
+    int i, j;
+
+    for(i = 0; papszLines[i] != NULL; i++)
+    {
+        const char *pszLine = papszLines[i];
+        for(j = 0; j < 21; j++)
+        {
+            if(pszLine[j] == ' ')
+            {
+                break;
+            }
+            szName[j] = pszLine[j];
+        }
+
+        if(j > 0)
+        {
+            szName[j] = 0;
+            papszIMD = CSLAddNameValue(papszIMD, szName, pszLine + 20);
+        }
+    }
+
+    CSLDestroy(papszLines);
+
+    return papszIMD;
+}
+
+/**
+ * GetAcqisitionTimeFromString()
+ */
+const time_t GDALMDReaderEROS::GetAcquisitionTimeFromString(
+        const char* pszDateTime)
+{
+    if(NULL == pszDateTime)
+        return 0;
+
+    int iYear;
+    int iMonth;
+    int iDay;
+    int iHours;
+    int iMin;
+    int iSec;
+
+    // exampe: sweep_start_utc     2013-04-22,11:35:02.50724
+
+    int r = sscanf ( pszDateTime, "%d-%d-%d,%d:%d:%d.%*d",
+                     &iYear, &iMonth, &iDay, &iHours, &iMin, &iSec);
+
+    if (r != 6)
+        return 0;
+
+    struct tm tmDateTime;
+    tmDateTime.tm_sec = iSec;
+    tmDateTime.tm_min = iMin;
+    tmDateTime.tm_hour = iHours;
+    tmDateTime.tm_mday = iDay;
+    tmDateTime.tm_mon = iMonth - 1;
+    tmDateTime.tm_year = iYear - 1900;
+    tmDateTime.tm_isdst = -1;
+
+    return mktime(&tmDateTime);
+}
diff --git a/gcore/mdreader/reader_geo_eye.h b/gcore/mdreader/reader_eros.h
similarity index 71%
copy from gcore/mdreader/reader_geo_eye.h
copy to gcore/mdreader/reader_eros.h
index d2644f5..3eeca11 100644
--- a/gcore/mdreader/reader_geo_eye.h
+++ b/gcore/mdreader/reader_eros.h
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: reader_geo_eye.h 29138 2015-05-03 19:12:48Z rouault $
+ * $Id$
  *
  * Project:  GDAL Core
- * Purpose:  Read metadata from GeoEye imagery.
+ * Purpose:  Read metadata from EROS imagery.
  * Author:   Alexander Lisovenko
  * Author:   Dmitry Baryshnikov, polimax at mail.ru
  *
@@ -27,41 +27,38 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
- 
-#ifndef READER_GEO_EYE_H_INCLUDED
-#define READER_GEO_EYE_H_INCLUDED
+
+#ifndef READER_EROS_H_INCLUDED
+#define READER_EROS_H_INCLUDED
 
 #include "../gdal_mdreader.h"
 
 /**
- at brief Metadata reader for Geo Eye
+ at brief Metadata reader for EROS
 
-TIFF filename:        aaaaaaaaaa.tif
-Metadata filename:    *_metadata*
-RPC filename:         aaaaaaaaaa_rpc.txt
+TIFF filename:      aaaaaaa.bb.ccc.tif
+Metadata filename:  aaaaaaa.pass
 
 Common metadata (from metadata filename):
-    MDName_SatelliteId:            Sensor
-    MDName_CloudCover:             Percent Cloud Cover
-    MDName_AcquisitionDateTime:    Acquisition Date/Time
-
+    SatelliteId:         satellite
+    AcquisitionDateTime: sweep_start_utc, sweep_end_utc
 */
 
-class GDALMDReaderGeoEye: public GDALMDReaderBase
+class GDALMDReaderEROS: public GDALMDReaderBase
 {
 public:
-    GDALMDReaderGeoEye(const char *pszPath, char **papszSiblingFiles);
-    virtual ~GDALMDReaderGeoEye();
+    GDALMDReaderEROS(const char *pszPath, char **papszSiblingFiles);
+    virtual ~GDALMDReaderEROS();
     virtual const bool HasRequiredFiles() const;
     virtual char** GetMetadataFiles() const;
 protected:
     virtual void LoadMetadata();
+    char** LoadImdTxtFile();
     virtual const time_t GetAcquisitionTimeFromString(const char* pszDateTime);
-    char **LoadRPCWktFile() const;
-    char **LoadIMDWktFile() const;
 protected:
     CPLString m_osIMDSourceFilename;
     CPLString m_osRPBSourceFilename;
 };
 
-#endif // READER_GEO_EYE_H_INCLUDED
+#endif // READER_EROS_H_INCLUDED
+
diff --git a/gcore/mdreader/reader_geo_eye.cpp b/gcore/mdreader/reader_geo_eye.cpp
index d364754..41132f6 100644
--- a/gcore/mdreader/reader_geo_eye.cpp
+++ b/gcore/mdreader/reader_geo_eye.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_geo_eye.cpp 29145 2015-05-04 10:00:40Z rouault $
+ * $Id: reader_geo_eye.cpp 29245 2015-05-24 16:46:56Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from GeoEye imagery.
@@ -30,7 +30,7 @@
  
 #include "reader_geo_eye.h"
 
-CPL_CVSID("$Id: reader_geo_eye.cpp 29145 2015-05-04 10:00:40Z rouault $");
+CPL_CVSID("$Id: reader_geo_eye.cpp 29245 2015-05-24 16:46:56Z rouault $");
 
 /**
  * GDALMDReaderGeoEye()
@@ -41,13 +41,16 @@ GDALMDReaderGeoEye::GDALMDReaderGeoEye(const char *pszPath,
     
     const char* pszBaseName = CPLGetBasename(pszPath);
     const char* pszDirName = CPLGetDirname(pszPath);
+    size_t nBaseNameLen = strlen(pszBaseName);
+    if( nBaseNameLen > 511 )
+        return;
 
     // get _metadata.txt file
     
     // split file name by _rgb_ or _pan_
     char szMetadataName[512] = {0};
     size_t i;
-    for(i = 0; i < CPLStrnlen(pszBaseName, 511); i++)
+    for(i = 0; i < nBaseNameLen; i++)
     {
         szMetadataName[i] = pszBaseName[i];
         if(EQUALN(pszBaseName + i, "_rgb_", 5) || EQUALN(pszBaseName + i, "_pan_", 5))
diff --git a/gcore/mdreader/reader_geo_eye.h b/gcore/mdreader/reader_geo_eye.h
index d2644f5..1d6f26c 100644
--- a/gcore/mdreader/reader_geo_eye.h
+++ b/gcore/mdreader/reader_geo_eye.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_geo_eye.h 29138 2015-05-03 19:12:48Z rouault $
+ * $Id: reader_geo_eye.h 29190 2015-05-13 21:40:30Z bishop $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from GeoEye imagery.
@@ -36,14 +36,14 @@
 /**
 @brief Metadata reader for Geo Eye
 
-TIFF filename:        aaaaaaaaaa.tif
-Metadata filename:    *_metadata*
-RPC filename:         aaaaaaaaaa_rpc.txt
+TIFF filename:      aaaaaaaaaa.tif
+Metadata filename:  *_metadata*
+RPC filename:       aaaaaaaaaa_rpc.txt
 
 Common metadata (from metadata filename):
-    MDName_SatelliteId:            Sensor
-    MDName_CloudCover:             Percent Cloud Cover
-    MDName_AcquisitionDateTime:    Acquisition Date/Time
+    SatelliteId:         Sensor
+    CloudCover:          Percent Cloud Cover
+    AcquisitionDateTime: Acquisition Date/Time
 
 */
 
diff --git a/gcore/mdreader/reader_kompsat.cpp b/gcore/mdreader/reader_kompsat.cpp
new file mode 100644
index 0000000..0f8ae66
--- /dev/null
+++ b/gcore/mdreader/reader_kompsat.cpp
@@ -0,0 +1,277 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL Core
+ * Purpose:  Read metadata from Kompsat imagery.
+ * Author:   Alexander Lisovenko
+ * Author:   Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014-2015 NextGIS <info at nextgis.ru>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "reader_kompsat.h"
+
+/**
+ * GDALMDReaderKompsat()
+ */
+GDALMDReaderKompsat::GDALMDReaderKompsat(const char *pszPath,
+        char **papszSiblingFiles) : GDALMDReaderBase(pszPath, papszSiblingFiles)
+{
+    m_osIMDSourceFilename = GDALFindAssociatedFile( pszPath, "TXT",
+                                                         papszSiblingFiles, 0 );
+    m_osRPBSourceFilename = GDALFindAssociatedFile( pszPath, "RPC",
+                                                         papszSiblingFiles, 0 );
+    
+    if(m_osIMDSourceFilename.size())
+        CPLDebug( "MDReaderDigitalGlobe", "IMD Filename: %s",
+              m_osIMDSourceFilename.c_str() );
+    if(m_osRPBSourceFilename.size())
+        CPLDebug( "MDReaderDigitalGlobe", "RPB Filename: %s",
+              m_osRPBSourceFilename.c_str() );
+}
+
+/**
+ * ~GDALMDReaderKompsat()
+ */
+GDALMDReaderKompsat::~GDALMDReaderKompsat()
+{
+}
+
+/**
+ * HasRequiredFiles()
+ */
+const bool GDALMDReaderKompsat::HasRequiredFiles() const
+{
+    if (!m_osIMDSourceFilename.empty() && !m_osRPBSourceFilename.empty())
+        return true;
+
+    return false;
+}
+
+/**
+ * GetMetadataFiles()
+ */
+char** GDALMDReaderKompsat::GetMetadataFiles() const
+{
+    char **papszFileList = NULL;
+    if(!m_osIMDSourceFilename.empty())
+        papszFileList= CSLAddString( papszFileList, m_osIMDSourceFilename );
+    if(!m_osRPBSourceFilename.empty())
+        papszFileList= CSLAddString( papszFileList, m_osRPBSourceFilename );
+
+    return papszFileList;
+}
+
+/**
+ * LoadMetadata()
+ */
+void GDALMDReaderKompsat::LoadMetadata()
+{
+    if(m_bIsMetadataLoad)
+        return;
+
+    if(!m_osIMDSourceFilename.empty())
+    {
+        m_papszIMDMD = ReadTxtToList( );
+    }
+
+    if(!m_osRPBSourceFilename.empty())
+    {
+        m_papszRPCMD = GDALLoadRPCFile( m_osRPBSourceFilename );
+    }
+
+    m_papszDEFAULTMD = CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "KARI");
+
+    m_bIsMetadataLoad = true;
+
+    const char* pszSatId1 = CSLFetchNameValue(m_papszIMDMD, "AUX_SATELLITE_NAME");
+    const char* pszSatId2 = CSLFetchNameValue(m_papszIMDMD, "AUX_SATELLITE_SENSOR");
+    if(NULL != pszSatId1 && NULL != pszSatId2)
+    {
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                           MD_NAME_SATELLITE, CPLSPrintf( "%s %s",
+                           CPLStripQuotes(pszSatId1).c_str(),
+                           CPLStripQuotes(pszSatId2).c_str()));
+    }
+    else if(NULL != pszSatId1 && NULL == pszSatId2)
+    {
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                MD_NAME_SATELLITE, CPLStripQuotes(pszSatId1));
+    }
+    else if(NULL == pszSatId1 && NULL != pszSatId2)
+    {
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                MD_NAME_SATELLITE, CPLStripQuotes(pszSatId2));
+    }
+
+    const char* pszCloudCover = CSLFetchNameValue(m_papszIMDMD,
+                                                 "AUX_CLOUD_STATUS");
+    if(NULL != pszCloudCover)
+    {
+        int nCC = atoi(pszCloudCover);
+        if(nCC > 100 || nCC < 0)
+        {
+            m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_CLOUDCOVER,
+                                               MD_CLOUDCOVER_NA);
+        }
+        else
+        {
+            m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                          MD_NAME_CLOUDCOVER, CPLSPrintf("%d", nCC));
+        }
+    }
+
+    const char* pszDate = CSLFetchNameValue(m_papszIMDMD,
+                                            "AUX_STRIP_ACQ_DATE_UT");
+    if(NULL != pszDate)
+    {
+        const char* pszTime = CSLFetchNameValue(m_papszIMDMD,
+                                                "AUX_STRIP_ACQ_START_UT");
+
+        if(NULL == pszTime)
+            pszTime = "000000.000000";
+
+        char buffer[80];
+        time_t timeMid = GetAcquisitionTimeFromString(CPLSPrintf( "%sT%s",
+                                                     pszDate, pszTime));
+        strftime (buffer, 80, MD_DATETIMEFORMAT, localtime(&timeMid));
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                           MD_NAME_ACQDATETIME, buffer);
+    }
+}
+
+/**
+ * ReadTxtToList
+ */
+char** GDALMDReaderKompsat::ReadTxtToList()
+{
+    char** papszLines = CSLLoad(m_osIMDSourceFilename);
+    if(NULL == papszLines)
+        return NULL;
+
+    char** papszIMD = NULL;
+    char szName[512];
+    int i;
+    size_t j;
+    CPLString soGroupName;
+
+    for(i = 0; papszLines[i] != NULL; i++)
+    {
+        const char *pszLine = papszLines[i];
+
+        //check if this is begin block
+        if(EQUALN(pszLine, "BEGIN_", 6))
+        {
+            for(j = 6; j < CPLStrnlen(pszLine, 512); j++)
+            {
+                if(EQUALN(pszLine + j, "_BLOCK", 6))
+                {
+                    szName[j - 6] = 0;
+                    break;
+                }
+                szName[j - 6] = pszLine[j];
+            }
+
+            soGroupName = szName;
+
+            continue;
+        }
+
+        //check if this is end block
+        if(EQUALN(pszLine, "END_", 4))
+        {
+            soGroupName.clear(); // we don't expect subblocks
+            continue;
+        }
+
+        //get name and value
+        for(j = 0; j < CPLStrnlen(pszLine, 512); j++)
+        {
+            if(pszLine[j] == '\t')
+            {
+                if(soGroupName.empty() || j > 0)
+                {
+                    szName[j] = 0;
+                    j++;
+                    break;
+                }
+                else
+                {
+                    continue;
+                }
+            }
+            szName[j] = pszLine[j];
+        }
+
+        // trim
+        while( pszLine[j] == ' ' && pszLine[j] != 0) j++;
+
+        if(soGroupName.empty())
+        {
+            papszIMD = CSLAddNameValue(papszIMD, szName, pszLine + j);
+        }
+        else
+        {
+            papszIMD = CSLAddNameValue(papszIMD, CPLSPrintf("%s.%s",
+                                       soGroupName.c_str(), szName), pszLine + j);
+        }
+
+    }
+
+    CSLDestroy(papszLines);
+
+    return papszIMD;
+}
+
+/**
+ * GetAcqisitionTimeFromString()
+ */
+const time_t GDALMDReaderKompsat::GetAcquisitionTimeFromString(
+        const char* pszDateTime)
+{
+    if(NULL == pszDateTime)
+        return 0;
+
+    int iYear;
+    int iMonth;
+    int iDay;
+    int iHours;
+    int iMin;
+    int iSec;
+
+    int r = sscanf ( pszDateTime, "%4d%2d%2dT%2d%2d%2d.%*s",
+                     &iYear, &iMonth, &iDay, &iHours, &iMin, &iSec);
+
+    if (r != 6)
+        return 0;
+
+    struct tm tmDateTime;
+    tmDateTime.tm_sec = iSec;
+    tmDateTime.tm_min = iMin;
+    tmDateTime.tm_hour = iHours;
+    tmDateTime.tm_mday = iDay;
+    tmDateTime.tm_mon = iMonth - 1;
+    tmDateTime.tm_year = iYear - 1900;
+    tmDateTime.tm_isdst = -1;
+
+    return mktime(&tmDateTime);
+}
diff --git a/gcore/mdreader/reader_pleiades.h b/gcore/mdreader/reader_kompsat.h
similarity index 70%
copy from gcore/mdreader/reader_pleiades.h
copy to gcore/mdreader/reader_kompsat.h
index 40a5ba5..d5306ae 100644
--- a/gcore/mdreader/reader_pleiades.h
+++ b/gcore/mdreader/reader_kompsat.h
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: reader_pleiades.h 29138 2015-05-03 19:12:48Z rouault $
+ * $Id$
  *
  * Project:  GDAL Core
- * Purpose:  Read metadata from Pleiades imagery.
+ * Purpose:  Read metadata from Kompsat imagery.
  * Author:   Alexander Lisovenko
  * Author:   Dmitry Baryshnikov, polimax at mail.ru
  *
@@ -28,37 +28,38 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef READER_PLEIADES_H_INCLUDED
-#define READER_PLEIADES_H_INCLUDED
+#ifndef READER_KOMPSAT_H_INCLUDED
+#define READER_KOMPSAT_H_INCLUDED
 
-#include "../gdal_mdreader.h"
+#include "reader_pleiades.h"
 
 /**
- at brief Metadata reader for Pleiades
+ at brief Metadata reader for Kompsat
 
-TIFF filename:        IMG_xxxxxx.tif
-Metadata filename:    DIM_xxxxxx.XML
-RPC filename:         RPC_xxxxxx.XML
+TIFF filename:      aaaaaaaaaa.tif
+Metadata filename:  aaaaaaaaaa.eph aaaaaaaaaa.txt
+RPC filename:       aaaaaaaaaa.rpc
 
 Common metadata (from metadata filename):
-    MDName_SatelliteId:            MISSION, MISSION_INDEX
-    MDName_AcquisitionDateTime:    IMAGING_DATE, IMAGING_TIME
-
+    SatelliteId:            AUX_SATELLITE_NAME
+    AcquisitionDateTime:    IMG_ACQISITION_START_TIME, IMG_ACQISITION_END_TIME
 */
 
-class GDALMDReaderPleiades: public GDALMDReaderBase
+class GDALMDReaderKompsat: public GDALMDReaderBase
 {
 public:
-    GDALMDReaderPleiades(const char *pszPath, char **papszSiblingFiles);
-    virtual ~GDALMDReaderPleiades();
+    GDALMDReaderKompsat(const char *pszPath, char **papszSiblingFiles);
+    virtual ~GDALMDReaderKompsat();
     virtual const bool HasRequiredFiles() const;
     virtual char** GetMetadataFiles() const;
 protected:
     virtual void LoadMetadata();
-    char** LoadRPCXmlFile();
+    char** ReadTxtToList();
+    virtual const time_t GetAcquisitionTimeFromString(const char* pszDateTime);
 protected:
     CPLString m_osIMDSourceFilename;
     CPLString m_osRPBSourceFilename;
 };
 
-#endif // READER_PLEIADES_H_INCLUDED
+#endif // READER_KOMPSAT_H_INCLUDED
+
diff --git a/gcore/mdreader/reader_landsat.cpp b/gcore/mdreader/reader_landsat.cpp
index e2918f1..56c8e7f 100644
--- a/gcore/mdreader/reader_landsat.cpp
+++ b/gcore/mdreader/reader_landsat.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_landsat.cpp 29145 2015-05-04 10:00:40Z rouault $
+ * $Id: reader_landsat.cpp 29245 2015-05-24 16:46:56Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Landsat imagery.
@@ -30,7 +30,7 @@
 
 #include "reader_landsat.h"
 
-CPL_CVSID("$Id: reader_landsat.cpp 29145 2015-05-04 10:00:40Z rouault $");
+CPL_CVSID("$Id: reader_landsat.cpp 29245 2015-05-24 16:46:56Z rouault $");
 
 /**
  * GDALMDReaderLandsat()
@@ -40,11 +40,14 @@ GDALMDReaderLandsat::GDALMDReaderLandsat(const char *pszPath,
 {
     const char* pszBaseName = CPLGetBasename(pszPath);
     const char* pszDirName = CPLGetDirname(pszPath);
+    size_t nBaseNameLen = strlen(pszBaseName);
+    if( nBaseNameLen > 511 )
+        return;
 
     // split file name by _B or _b
     char szMetadataName[512] = {0};
     size_t i;
-    for(i = 0; i < CPLStrnlen(pszBaseName, 511); i++)
+    for(i = 0; i < nBaseNameLen; i++)
     {
         szMetadataName[i] = pszBaseName[i];
         if(EQUALN(pszBaseName + i, "_B", 2) || EQUALN(pszBaseName + i, "_b", 2))
@@ -56,9 +59,6 @@ GDALMDReaderLandsat::GDALMDReaderLandsat(const char *pszPath,
     // form metadata file name
     CPLStrlcpy(szMetadataName + i, "_MTL.txt", 9);
 
-    //CPLDebug( "MDReaderLandsat", "Try IMD Filename: %s",
-    //        szMetadataName );
-
     const char* pszIMDSourceFilename = CPLFormFilename( pszDirName,
                                                         szMetadataName, NULL );
     if (CPLCheckForFile((char*)pszIMDSourceFilename, papszSiblingFiles))
diff --git a/gcore/mdreader/reader_landsat.h b/gcore/mdreader/reader_landsat.h
index b59f761..e54ce43 100644
--- a/gcore/mdreader/reader_landsat.h
+++ b/gcore/mdreader/reader_landsat.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_landsat.h 29138 2015-05-03 19:12:48Z rouault $
+ * $Id: reader_landsat.h 29190 2015-05-13 21:40:30Z bishop $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Landsat imagery.
@@ -36,16 +36,16 @@
 /**
 @brief Metadata reader for Landsat
 
-TIFF filename:		xxxxxx_aaa.tif
-Metadata filename:	xxxxxx_MTL.txt
+TIFF filename:      xxxxxx_aaa.tif
+Metadata filename:  xxxxxx_MTL.txt
 RPC filename:           
 
 Common metadata (from metadata filename):
-        MDName_SatelliteId:         SPACECRAFT_ID
-        MDName_CloudCover:          CLOUD_COVER (Landsat 8)
-        MDName_AcquisitionDateTime: ACQUISITION_DATE,
-                                    SCENE_CENTER_SCAN_TIME (Landsat 5,7) or
-                                    DATE_ACQUIRED, SCENE_CENTER_TIME (Landsat 8);
+    SatelliteId:         SPACECRAFT_ID
+    CloudCover:          CLOUD_COVER (Landsat 8)
+    AcquisitionDateTime: ACQUISITION_DATE,
+                         SCENE_CENTER_SCAN_TIME (Landsat 5,7) or
+                         DATE_ACQUIRED, SCENE_CENTER_TIME (Landsat 8);
 
 */
 
diff --git a/gcore/mdreader/reader_orb_view.h b/gcore/mdreader/reader_orb_view.h
index 9185078..22c727e 100644
--- a/gcore/mdreader/reader_orb_view.h
+++ b/gcore/mdreader/reader_orb_view.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_orb_view.h 29138 2015-05-03 19:12:48Z rouault $
+ * $Id: reader_orb_view.h 29190 2015-05-13 21:40:30Z bishop $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from OrbView imagery.
@@ -36,14 +36,14 @@
 /**
 @brief Metadata reader for OrbView
 
-TIFF filename:        aaaaaaaaa.tif
-Metadata filename:    aaaaaaaaa.pvl
-RPC filename:         aaaaaaaaa_rpc.txt
+TIFF filename:      aaaaaaaaa.tif
+Metadata filename:  aaaaaaaaa.pvl
+RPC filename:       aaaaaaaaa_rpc.txt
 
 Common metadata (from metadata filename):
-    MDName_SatelliteId:         sensorInfo.satelliteName
-    MDName_CloudCover:          productInfo.productCloudCoverPercentage
-    MDName_AcquisitionDateTime: inputImageInfo.firstLineAcquisitionDateTime
+    SatelliteId:         sensorInfo.satelliteName
+    CloudCover:          productInfo.productCloudCoverPercentage
+    AcquisitionDateTime: inputImageInfo.firstLineAcquisitionDateTime
 */
 class GDALMDReaderOrbView: public GDALMDReaderBase
 {
diff --git a/gcore/mdreader/reader_pleiades.cpp b/gcore/mdreader/reader_pleiades.cpp
index 75ad6e9..160fa0c 100644
--- a/gcore/mdreader/reader_pleiades.cpp
+++ b/gcore/mdreader/reader_pleiades.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_pleiades.cpp 29145 2015-05-04 10:00:40Z rouault $
+ * $Id: reader_pleiades.cpp 29245 2015-05-24 16:46:56Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Pleiades imagery.
@@ -30,7 +30,7 @@
 
 #include "reader_pleiades.h"
 
-CPL_CVSID("$Id: reader_pleiades.cpp 29145 2015-05-04 10:00:40Z rouault $");
+CPL_CVSID("$Id: reader_pleiades.cpp 29245 2015-05-24 16:46:56Z rouault $");
 
 /**
  * GDALMDReaderPleiades()
@@ -39,6 +39,9 @@ GDALMDReaderPleiades::GDALMDReaderPleiades(const char *pszPath,
         char **papszSiblingFiles) : GDALMDReaderBase(pszPath, papszSiblingFiles)
 {
     const char* pszBaseName = CPLGetBasename(pszPath);
+    size_t nBaseNameLen = strlen(pszBaseName);
+    if( nBaseNameLen < 4 || nBaseNameLen > 511 )
+        return;
 
     const char* pszDirName = CPLGetDirname(pszPath);
 
@@ -50,7 +53,7 @@ GDALMDReaderPleiades::GDALMDReaderPleiades(const char *pszPath,
     // find last underline
     char sBaseName[512];
     int nLastUnderline = 0;
-    for(size_t i = 4; i < CPLStrnlen(pszBaseName, 512); i++)
+    for(size_t i = 4; i < nBaseNameLen; i++)
     {
         sBaseName[i - 4] = pszBaseName[i];
         if(pszBaseName[i] == '_')
diff --git a/gcore/mdreader/reader_pleiades.h b/gcore/mdreader/reader_pleiades.h
index 40a5ba5..cdcba6b 100644
--- a/gcore/mdreader/reader_pleiades.h
+++ b/gcore/mdreader/reader_pleiades.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_pleiades.h 29138 2015-05-03 19:12:48Z rouault $
+ * $Id: reader_pleiades.h 29190 2015-05-13 21:40:30Z bishop $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Pleiades imagery.
@@ -36,13 +36,13 @@
 /**
 @brief Metadata reader for Pleiades
 
-TIFF filename:        IMG_xxxxxx.tif
-Metadata filename:    DIM_xxxxxx.XML
-RPC filename:         RPC_xxxxxx.XML
+TIFF filename:      IMG_xxxxxx.tif
+Metadata filename:  DIM_xxxxxx.XML
+RPC filename:       RPC_xxxxxx.XML
 
 Common metadata (from metadata filename):
-    MDName_SatelliteId:            MISSION, MISSION_INDEX
-    MDName_AcquisitionDateTime:    IMAGING_DATE, IMAGING_TIME
+    SatelliteId:         MISSION, MISSION_INDEX
+    AcquisitionDateTime: IMAGING_DATE, IMAGING_TIME
 
 */
 
diff --git a/gcore/mdreader/reader_rapid_eye.cpp b/gcore/mdreader/reader_rapid_eye.cpp
new file mode 100644
index 0000000..beefa37
--- /dev/null
+++ b/gcore/mdreader/reader_rapid_eye.cpp
@@ -0,0 +1,155 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL Core
+ * Purpose:  Read metadata from RapidEye imagery.
+ * Author:   Alexander Lisovenko
+ * Author:   Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014-2015 NextGIS <info at nextgis.ru>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "reader_rapid_eye.h"
+
+/**
+ * GDALMDReaderRapidEye()
+ */
+GDALMDReaderRapidEye::GDALMDReaderRapidEye(const char *pszPath,
+        char **papszSiblingFiles) : GDALMDReaderBase(pszPath, papszSiblingFiles)
+{
+    const char* pszDirName = CPLGetDirname(pszPath);
+    const char* pszBaseName = CPLGetBasename(pszPath);
+
+    const char* pszIMDSourceFilename = CPLFormFilename( pszDirName,
+                                                        CPLSPrintf("%s_metadata",
+                                                        pszBaseName), "xml" );
+    if (CPLCheckForFile((char*)pszIMDSourceFilename, papszSiblingFiles))
+    {
+        m_osXMLSourceFilename = pszIMDSourceFilename;
+    }
+    else
+    {
+        pszIMDSourceFilename = CPLFormFilename( pszDirName,
+                                                CPLSPrintf("%s_METADATA",
+                                                pszBaseName), "XML" );
+        if (CPLCheckForFile((char*)pszIMDSourceFilename, papszSiblingFiles))
+        {
+            m_osXMLSourceFilename = pszIMDSourceFilename;
+        }
+    }
+
+    if(m_osXMLSourceFilename.size())
+        CPLDebug( "MDReaderRapidEye", "XML Filename: %s",
+              m_osXMLSourceFilename.c_str() );
+}
+
+/**
+ * ~GDALMDReaderRapidEye()
+ */
+GDALMDReaderRapidEye::~GDALMDReaderRapidEye()
+{
+}
+
+/**
+ * HasRequiredFiles()
+ */
+const bool GDALMDReaderRapidEye::HasRequiredFiles() const
+{
+    // check re:EarthObservation
+    if (!m_osXMLSourceFilename.empty() &&
+            GDALCheckFileHeader(m_osXMLSourceFilename, "re:EarthObservation"))
+        return true;
+
+    return false;
+}
+
+/**
+ * GetMetadataFiles()
+ */
+char** GDALMDReaderRapidEye::GetMetadataFiles() const
+{
+    char **papszFileList = NULL;
+    if(!m_osXMLSourceFilename.empty())
+        papszFileList= CSLAddString( papszFileList, m_osXMLSourceFilename );
+
+    return papszFileList;
+}
+
+/**
+ * LoadMetadata()
+ */
+void GDALMDReaderRapidEye::LoadMetadata()
+{
+    if(m_bIsMetadataLoad)
+        return;
+
+    CPLXMLNode* psNode = CPLParseXMLFile(m_osXMLSourceFilename);
+
+    if(psNode != NULL)
+    {
+        CPLXMLNode* pRootNode = CPLSearchXMLNode(psNode, "=re:EarthObservation");
+
+        if(pRootNode != NULL)
+        {
+            m_papszIMDMD = ReadXMLToList(pRootNode->psChild, m_papszIMDMD);
+        }
+        CPLDestroyXMLNode(psNode);
+    }
+
+    m_papszDEFAULTMD = CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "RE");
+
+    m_bIsMetadataLoad = true;
+
+    if(NULL == m_papszIMDMD)
+    {
+        return;
+    }
+
+    //extract imagery metadata
+    const char* pszSatId = CSLFetchNameValue(m_papszIMDMD,
+    "gml:using.eop:EarthObservationEquipment.eop:platform.eop:Platform.eop:serialIdentifier");
+    if(NULL != pszSatId)
+    {
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                MD_NAME_SATELLITE, CPLStripQuotes(pszSatId));
+    }
+
+    const char* pszDateTime = CSLFetchNameValue(m_papszIMDMD,
+    "gml:using.eop:EarthObservationEquipment.eop:acquisitionParameters.re:Acquisition.re:acquisitionDateTime");
+    if(NULL != pszDateTime)
+    {
+        char buffer[80];
+        time_t timeMid = GetAcquisitionTimeFromString(pszDateTime);
+        strftime (buffer, 80, MD_DATETIMEFORMAT, localtime(&timeMid));
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                           MD_NAME_ACQDATETIME, buffer);
+    }
+
+    const char* pszCC = CSLFetchNameValue(m_papszIMDMD,
+    "gml:resultOf.re:EarthObservationResult.opt:cloudCoverPercentage");
+    if(NULL != pszSatId)
+    {
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                MD_NAME_CLOUDCOVER, pszCC);
+    }
+
+}
diff --git a/gcore/mdreader/reader_pleiades.h b/gcore/mdreader/reader_rapid_eye.h
similarity index 70%
copy from gcore/mdreader/reader_pleiades.h
copy to gcore/mdreader/reader_rapid_eye.h
index 40a5ba5..bf94321 100644
--- a/gcore/mdreader/reader_pleiades.h
+++ b/gcore/mdreader/reader_rapid_eye.h
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: reader_pleiades.h 29138 2015-05-03 19:12:48Z rouault $
+ * $Id$
  *
  * Project:  GDAL Core
- * Purpose:  Read metadata from Pleiades imagery.
+ * Purpose:  Read metadata from RapidEye imagery.
  * Author:   Alexander Lisovenko
  * Author:   Dmitry Baryshnikov, polimax at mail.ru
  *
@@ -28,37 +28,36 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef READER_PLEIADES_H_INCLUDED
-#define READER_PLEIADES_H_INCLUDED
+#ifndef READER_RAPID_EYE_H_INCLUDED
+#define READER_RAPID_EYE_H_INCLUDED
 
 #include "../gdal_mdreader.h"
 
 /**
- at brief Metadata reader for Pleiades
+ at brief Metadata reader for RapidEye
 
-TIFF filename:        IMG_xxxxxx.tif
-Metadata filename:    DIM_xxxxxx.XML
-RPC filename:         RPC_xxxxxx.XML
+TIFF filename:      aaaaaaaa.tif
+Metadata filename:  aaaaaaaa_metadata.xml
+RPC filename:
 
 Common metadata (from metadata filename):
-    MDName_SatelliteId:            MISSION, MISSION_INDEX
-    MDName_AcquisitionDateTime:    IMAGING_DATE, IMAGING_TIME
-
+    SatelliteId:         eop:serialIdentifier
+    CloudCover:          opt:cloudCoverPercentage
+    AcquisitionDateTime: re:acquisitionDateTime
 */
 
-class GDALMDReaderPleiades: public GDALMDReaderBase
+class GDALMDReaderRapidEye: public GDALMDReaderBase
 {
 public:
-    GDALMDReaderPleiades(const char *pszPath, char **papszSiblingFiles);
-    virtual ~GDALMDReaderPleiades();
+    GDALMDReaderRapidEye(const char *pszPath, char **papszSiblingFiles);
+    virtual ~GDALMDReaderRapidEye();
     virtual const bool HasRequiredFiles() const;
     virtual char** GetMetadataFiles() const;
 protected:
     virtual void LoadMetadata();
-    char** LoadRPCXmlFile();
 protected:
-    CPLString m_osIMDSourceFilename;
-    CPLString m_osRPBSourceFilename;
+    CPLString m_osXMLSourceFilename;
 };
 
-#endif // READER_PLEIADES_H_INCLUDED
+#endif // READER_RAPID_EYE_H_INCLUDED
+
diff --git a/gcore/mdreader/reader_rdk1.h b/gcore/mdreader/reader_rdk1.h
index c096423..1859e0c 100644
--- a/gcore/mdreader/reader_rdk1.h
+++ b/gcore/mdreader/reader_rdk1.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_rdk1.h 29138 2015-05-03 19:12:48Z rouault $
+ * $Id: reader_rdk1.h 29190 2015-05-13 21:40:30Z bishop $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Resurs-DK1 imagery.
@@ -36,13 +36,13 @@
 /**
 @brief Metadata reader for RDK1
 
-TIFF filename:		aaaaaaaaaa.tif
-Metadata filename:	aaaaaaaaaa.xml
+TIFF filename:      aaaaaaaaaa.tif
+Metadata filename:  aaaaaaaaaa.xml
 RPC filename:
 
 Common metadata (from metadata filename):
-        MDName_SatelliteId:			cCodeKA
-        MDName_AcquisitionDateTime:	dSceneDate, tSceneTime
+    SatelliteId:         cCodeKA
+    AcquisitionDateTime: dSceneDate, tSceneTime
 */
 
 class GDALMDReaderResursDK1: public GDALMDReaderBase
diff --git a/gcore/mdreader/reader_spot.cpp b/gcore/mdreader/reader_spot.cpp
new file mode 100644
index 0000000..f56276a
--- /dev/null
+++ b/gcore/mdreader/reader_spot.cpp
@@ -0,0 +1,315 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL Core
+ * Purpose:  Read metadata from Spot imagery.
+ * Author:   Alexander Lisovenko
+ * Author:   Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2014-2015 NextGIS <info at nextgis.ru>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "reader_spot.h"
+
+/**
+ * GDALMDReaderSpot()
+ */
+GDALMDReaderSpot::GDALMDReaderSpot(const char *pszPath,
+        char **papszSiblingFiles) : GDALMDReaderPleiades(pszPath, papszSiblingFiles)
+{
+    const char* pszIMDSourceFilename;
+    const char* pszDirName = CPLGetDirname(pszPath);
+
+    if(m_osIMDSourceFilename.empty())
+    {        
+        pszIMDSourceFilename = CPLFormFilename( pszDirName, "METADATA.DIM", NULL );
+
+        if (CPLCheckForFile((char*)pszIMDSourceFilename, papszSiblingFiles))
+        {
+            m_osIMDSourceFilename = pszIMDSourceFilename;
+        }
+        else
+        {
+            pszIMDSourceFilename = CPLFormFilename( pszDirName, "metadata.dim", NULL );
+            if (CPLCheckForFile((char*)pszIMDSourceFilename, papszSiblingFiles))
+            {
+                m_osIMDSourceFilename = pszIMDSourceFilename;
+            }
+        }
+    }
+
+    // if the file name ended on METADATA.DIM
+    // Linux specific
+    // example: R2_CAT_091028105025131_1\METADATA.DIM
+    if(m_osIMDSourceFilename.empty())
+    {
+        if(EQUAL(CPLGetFilename(pszPath), "IMAGERY.TIF"))
+        {
+            pszIMDSourceFilename = CPLSPrintf( "%s\\METADATA.DIM",
+                                                           CPLGetPath(pszPath));
+
+            if (CPLCheckForFile((char*)pszIMDSourceFilename, papszSiblingFiles))
+            {
+                m_osIMDSourceFilename = pszIMDSourceFilename;
+            }
+            else
+            {
+                pszIMDSourceFilename = CPLSPrintf( "%s\\metadata.dim",
+                                                           CPLGetPath(pszPath));
+                if (CPLCheckForFile((char*)pszIMDSourceFilename, papszSiblingFiles))
+                {
+                    m_osIMDSourceFilename = pszIMDSourceFilename;
+                }
+            }
+        }
+    }
+
+    if(m_osIMDSourceFilename.size())
+        CPLDebug( "MDReaderSpot", "IMD Filename: %s",
+              m_osIMDSourceFilename.c_str() );
+}
+
+/**
+ * ~GDALMDReaderSpot()
+ */
+GDALMDReaderSpot::~GDALMDReaderSpot()
+{
+}
+
+/**
+ * LoadMetadata()
+ */
+void GDALMDReaderSpot::LoadMetadata()
+{
+    if(m_bIsMetadataLoad)
+        return;
+
+    if (!m_osIMDSourceFilename.empty())
+    {
+        CPLXMLNode* psNode = CPLParseXMLFile(m_osIMDSourceFilename);
+
+        if(psNode != NULL)
+        {
+            CPLXMLNode* psisdNode = CPLSearchXMLNode(psNode, "=Dimap_Document");
+
+            if(psisdNode != NULL)
+            {
+                m_papszIMDMD = ReadXMLToList(psisdNode->psChild, m_papszIMDMD);
+            }
+            CPLDestroyXMLNode(psNode);
+        }
+    }
+
+    m_papszDEFAULTMD = CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "DIMAP");
+
+    m_bIsMetadataLoad = true;
+
+    if(NULL == m_papszIMDMD)
+    {
+        return;
+    }
+
+    //extract imagery metadata
+    int nCounter = -1;
+    const char* pszSatId1 = CSLFetchNameValue(m_papszIMDMD,
+                  "Dataset_Sources.Source_Information.Scene_Source.MISSION");
+    if(NULL == pszSatId1)
+    {
+        nCounter = 1;
+        for(int i = 0; i < 5; i++)
+        {
+            pszSatId1 = CSLFetchNameValue(m_papszIMDMD,
+            CPLSPrintf("Dataset_Sources.Source_Information_%d.Scene_Source.MISSION",
+                       nCounter));
+            if(NULL != pszSatId1)
+                break;
+            nCounter++;
+        }
+    }
+
+
+    const char* pszSatId2;
+    if(nCounter == -1)
+        pszSatId2 = CSLFetchNameValue(m_papszIMDMD,
+            "Dataset_Sources.Source_Information.Scene_Source.MISSION_INDEX");
+    else
+        pszSatId2 = CSLFetchNameValue(m_papszIMDMD, CPLSPrintf(
+            "Dataset_Sources.Source_Information_%d.Scene_Source.MISSION_INDEX",
+            nCounter));
+
+    if(NULL != pszSatId1 && NULL != pszSatId2)
+    {
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                           MD_NAME_SATELLITE, CPLSPrintf( "%s %s",
+                           CPLStripQuotes(pszSatId1).c_str(),
+                           CPLStripQuotes(pszSatId2).c_str()));
+    }
+    else if(NULL != pszSatId1 && NULL == pszSatId2)
+    {
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                MD_NAME_SATELLITE, CPLStripQuotes(pszSatId1));
+    }
+    else if(NULL == pszSatId1 && NULL != pszSatId2)
+    {
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                MD_NAME_SATELLITE, CPLStripQuotes(pszSatId2));
+    }
+
+
+    const char* pszDate;
+    if(nCounter == -1)
+        pszDate = CSLFetchNameValue(m_papszIMDMD,
+             "Dataset_Sources.Source_Information.Scene_Source.IMAGING_DATE");
+    else
+        pszDate = CSLFetchNameValue(m_papszIMDMD, CPLSPrintf(
+             "Dataset_Sources.Source_Information_%d.Scene_Source.IMAGING_DATE",
+             nCounter));
+
+    if(NULL != pszDate)
+    {
+        const char* pszTime;
+        if(nCounter == -1)
+            pszTime = CSLFetchNameValue(m_papszIMDMD,
+             "Dataset_Sources.Source_Information.Scene_Source.IMAGING_TIME");
+        else
+            pszTime = CSLFetchNameValue(m_papszIMDMD, CPLSPrintf(
+             "Dataset_Sources.Source_Information_%d.Scene_Source.IMAGING_TIME",
+             nCounter));
+
+        if(NULL == pszTime)
+            pszTime = "00:00:00.0Z";
+
+        char buffer[80];
+        time_t timeMid = GetAcquisitionTimeFromString(CPLSPrintf( "%sT%s",
+                                                     pszDate, pszTime));
+        strftime (buffer, 80, MD_DATETIMEFORMAT, localtime(&timeMid));
+        m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
+                                           MD_NAME_ACQDATETIME, buffer);
+    }
+
+    m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_CLOUDCOVER,
+                                       MD_CLOUDCOVER_NA);
+}
+
+
+/**
+ * ReadXMLToList()
+ */
+char** GDALMDReaderSpot::ReadXMLToList(CPLXMLNode* psNode, char** papszList,
+                                          const char* pszName)
+{
+    if(NULL == psNode)
+        return papszList;
+
+    if (psNode->eType == CXT_Text)
+    {
+        if(!EQUAL(pszName, ""))
+            return AddXMLNameValueToList(papszList, pszName, psNode->pszValue);
+    }
+
+    if (psNode->eType == CXT_Element && !EQUAL(psNode->pszValue, "Data_Strip"))
+    {
+        int nAddIndex = 0;
+        bool bReset = false;
+        for(CPLXMLNode* psChildNode = psNode->psChild; NULL != psChildNode;
+            psChildNode = psChildNode->psNext)
+        {
+            if (psChildNode->eType == CXT_Element)
+            {
+                // check name duplicates
+                if(NULL != psChildNode->psNext)
+                {
+                    if(bReset)
+                    {
+                        bReset = false;
+                        nAddIndex = 0;
+                    }
+
+                    if(EQUAL(psChildNode->pszValue, psChildNode->psNext->pszValue))
+                    {
+                        nAddIndex++;
+                    }
+                    else
+                    { // the name changed
+
+                        if(nAddIndex > 0)
+                        {
+                            bReset = true;
+                            nAddIndex++;
+                        }
+                    }
+                }
+                else
+                {
+                    if(nAddIndex > 0)
+                    {
+                        nAddIndex++;
+                    }
+                }
+
+                char szName[512];
+                if(nAddIndex > 0)
+                {
+                    CPLsnprintf( szName, 511, "%s_%d", psChildNode->pszValue,
+                                 nAddIndex);
+                }
+                else
+                {
+                    CPLStrlcpy(szName, psChildNode->pszValue, 511);
+                }
+
+                char szNameNew[512];
+                if(CPLStrnlen( pszName, 511 ) > 0) //if no prefix just set name to node name
+                {
+                    CPLsnprintf( szNameNew, 511, "%s.%s", pszName, szName );
+                }
+                else
+                {
+                    CPLsnprintf( szNameNew, 511, "%s.%s", psNode->pszValue, szName );
+                }
+
+                papszList = ReadXMLToList(psChildNode, papszList, szNameNew);
+            }
+            else
+            {
+                // Text nodes should always have name
+                if(EQUAL(pszName, ""))
+                {
+                    papszList = ReadXMLToList(psChildNode, papszList, psNode->pszValue);
+                }
+                else
+                {
+                    papszList = ReadXMLToList(psChildNode, papszList, pszName);
+                }
+            }
+        }
+    }
+
+    // proceed next only on top level
+
+    if(NULL != psNode->psNext && EQUAL(pszName, ""))
+    {
+         papszList = ReadXMLToList(psNode->psNext, papszList, pszName);
+    }
+
+    return papszList;
+}
diff --git a/gcore/mdreader/reader_pleiades.h b/gcore/mdreader/reader_spot.h
similarity index 64%
copy from gcore/mdreader/reader_pleiades.h
copy to gcore/mdreader/reader_spot.h
index 40a5ba5..c8809c3 100644
--- a/gcore/mdreader/reader_pleiades.h
+++ b/gcore/mdreader/reader_spot.h
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: reader_pleiades.h 29138 2015-05-03 19:12:48Z rouault $
+ * $Id$
  *
  * Project:  GDAL Core
- * Purpose:  Read metadata from Pleiades imagery.
+ * Purpose:  Read metadata from Spot imagery.
  * Author:   Alexander Lisovenko
  * Author:   Dmitry Baryshnikov, polimax at mail.ru
  *
@@ -28,37 +28,33 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef READER_PLEIADES_H_INCLUDED
-#define READER_PLEIADES_H_INCLUDED
+#ifndef READER_SPOT_H_INCLUDED
+#define READER_SPOT_H_INCLUDED
 
-#include "../gdal_mdreader.h"
+#include "reader_pleiades.h"
 
 /**
- at brief Metadata reader for Pleiades
+ at brief Metadata reader for Spot
 
-TIFF filename:        IMG_xxxxxx.tif
-Metadata filename:    DIM_xxxxxx.XML
-RPC filename:         RPC_xxxxxx.XML
+TIFF filename:      aaaaaaaaaa.tif
+Metadata filename:  METADATA.DIM
+RPC filename:
 
 Common metadata (from metadata filename):
-    MDName_SatelliteId:            MISSION, MISSION_INDEX
-    MDName_AcquisitionDateTime:    IMAGING_DATE, IMAGING_TIME
-
+    SatelliteId:         MISSION, MISSION_INDEX
+    AcquisitionDateTime: IMAGING_DATE, IMAGING_TIME
 */
 
-class GDALMDReaderPleiades: public GDALMDReaderBase
+class GDALMDReaderSpot: public GDALMDReaderPleiades
 {
 public:
-    GDALMDReaderPleiades(const char *pszPath, char **papszSiblingFiles);
-    virtual ~GDALMDReaderPleiades();
-    virtual const bool HasRequiredFiles() const;
-    virtual char** GetMetadataFiles() const;
+    GDALMDReaderSpot(const char *pszPath, char **papszSiblingFiles);
+    virtual ~GDALMDReaderSpot();
 protected:
     virtual void LoadMetadata();
-    char** LoadRPCXmlFile();
-protected:
-    CPLString m_osIMDSourceFilename;
-    CPLString m_osRPBSourceFilename;
+    virtual char** ReadXMLToList(CPLXMLNode* psNode, char** papszList,
+                                 const char* pszName = "");
 };
 
-#endif // READER_PLEIADES_H_INCLUDED
+#endif // READER_SPOT_H_INCLUDED
+
diff --git a/gcore/rasterio.cpp b/gcore/rasterio.cpp
index ba0ffb3..af16a6a 100644
--- a/gcore/rasterio.cpp
+++ b/gcore/rasterio.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rasterio.cpp 28620 2015-03-05 16:56:28Z rouault $
+ * $Id: rasterio.cpp 29161 2015-05-06 10:18:19Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Contains default implementation of GDALRasterBand::IRasterIO()
@@ -52,7 +52,7 @@
 #endif
 
 
-CPL_CVSID("$Id: rasterio.cpp 28620 2015-03-05 16:56:28Z rouault $");
+CPL_CVSID("$Id: rasterio.cpp 29161 2015-05-06 10:18:19Z rouault $");
 
 /************************************************************************/
 /*                             IRasterIO()                              */
@@ -3679,6 +3679,8 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
                                                 (nBlocksDone + 0.5) / (double)nTotalBlocks,
                                                 pfnProgress,
                                                 pProgressData );
+                    if( sExtraArg.pProgressData == NULL )
+                        sExtraArg.pfnProgress = NULL;
 
                     eErr = poSrcDS->RasterIO( GF_Read, 
                                             iX, iY, nThisCols, nThisLines,
@@ -3742,6 +3744,8 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
                                             (nBlocksDone + 0.5) / (double)nTotalBlocks,
                                             pfnProgress,
                                             pProgressData );
+                if( sExtraArg.pProgressData == NULL )
+                    sExtraArg.pfnProgress = NULL;
 
                 eErr = poSrcDS->RasterIO( GF_Read, 
                                         iX, iY, nThisCols, nThisLines,
diff --git a/man/man1/gdal-config.1 b/man/man1/gdal-config.1
index 19abb8c..34f17ba 100644
--- a/man/man1/gdal-config.1
+++ b/man/man1/gdal-config.1
@@ -1,8 +1,8 @@
-.TH "gdal-config" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal-config" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal-config \- .TH "gdal-config" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal-config \- .TH "gdal-config" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal2tiles.1 b/man/man1/gdal2tiles.1
index 5b606ca..894be80 100644
--- a/man/man1/gdal2tiles.1
+++ b/man/man1/gdal2tiles.1
@@ -1,8 +1,8 @@
-.TH "gdal2tiles" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal2tiles" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal2tiles \- .TH "gdal2tiles" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal2tiles \- .TH "gdal2tiles" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_calc.1 b/man/man1/gdal_calc.1
index f95d437..3666875 100644
--- a/man/man1/gdal_calc.1
+++ b/man/man1/gdal_calc.1
@@ -1,8 +1,8 @@
-.TH "gdal_calc" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal_calc" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_calc \- .TH "gdal_calc" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal_calc \- .TH "gdal_calc" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_contour.1 b/man/man1/gdal_contour.1
index 75555ba..58f5927 100644
--- a/man/man1/gdal_contour.1
+++ b/man/man1/gdal_contour.1
@@ -1,8 +1,8 @@
-.TH "gdal_contour" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal_contour" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_contour \- .TH "gdal_contour" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal_contour \- .TH "gdal_contour" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_edit.1 b/man/man1/gdal_edit.1
index b613548..7918829 100644
--- a/man/man1/gdal_edit.1
+++ b/man/man1/gdal_edit.1
@@ -1,8 +1,8 @@
-.TH "gdal_edit" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal_edit" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_edit \- .TH "gdal_edit" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal_edit \- .TH "gdal_edit" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_fillnodata.1 b/man/man1/gdal_fillnodata.1
index dda1d3c..ff1e4a4 100644
--- a/man/man1/gdal_fillnodata.1
+++ b/man/man1/gdal_fillnodata.1
@@ -1,8 +1,8 @@
-.TH "gdal_fillnodata" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal_fillnodata" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_fillnodata \- .TH "gdal_fillnodata" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal_fillnodata \- .TH "gdal_fillnodata" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_grid.1 b/man/man1/gdal_grid.1
index c0ff49d..8d7dadf 100644
--- a/man/man1/gdal_grid.1
+++ b/man/man1/gdal_grid.1
@@ -1,8 +1,8 @@
-.TH "gdal_grid" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal_grid" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_grid \- .TH "gdal_grid" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal_grid \- .TH "gdal_grid" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_merge.1 b/man/man1/gdal_merge.1
index ca89b55..acbe2a5 100644
--- a/man/man1/gdal_merge.1
+++ b/man/man1/gdal_merge.1
@@ -1,8 +1,8 @@
-.TH "gdal_merge" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal_merge" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_merge \- .TH "gdal_merge" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal_merge \- .TH "gdal_merge" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_polygonize.1 b/man/man1/gdal_polygonize.1
index cdbdbcf..8aac1d4 100644
--- a/man/man1/gdal_polygonize.1
+++ b/man/man1/gdal_polygonize.1
@@ -1,8 +1,8 @@
-.TH "gdal_polygonize" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal_polygonize" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_polygonize \- .TH "gdal_polygonize" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal_polygonize \- .TH "gdal_polygonize" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_proximity.1 b/man/man1/gdal_proximity.1
index cd6beeb..c8b1c6a 100644
--- a/man/man1/gdal_proximity.1
+++ b/man/man1/gdal_proximity.1
@@ -1,8 +1,8 @@
-.TH "gdal_proximity" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal_proximity" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_proximity \- .TH "gdal_proximity" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal_proximity \- .TH "gdal_proximity" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_rasterize.1 b/man/man1/gdal_rasterize.1
index 775bd13..0e4bc60 100644
--- a/man/man1/gdal_rasterize.1
+++ b/man/man1/gdal_rasterize.1
@@ -1,8 +1,8 @@
-.TH "gdal_rasterize" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal_rasterize" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_rasterize \- .TH "gdal_rasterize" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal_rasterize \- .TH "gdal_rasterize" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_retile.1 b/man/man1/gdal_retile.1
index 67f8b2c..1c483c6 100644
--- a/man/man1/gdal_retile.1
+++ b/man/man1/gdal_retile.1
@@ -1,8 +1,8 @@
-.TH "gdal_retile" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal_retile" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_retile \- .TH "gdal_retile" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal_retile \- .TH "gdal_retile" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_sieve.1 b/man/man1/gdal_sieve.1
index 0ff2b97..f365756 100644
--- a/man/man1/gdal_sieve.1
+++ b/man/man1/gdal_sieve.1
@@ -1,8 +1,8 @@
-.TH "gdal_sieve" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal_sieve" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_sieve \- .TH "gdal_sieve" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal_sieve \- .TH "gdal_sieve" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_translate.1 b/man/man1/gdal_translate.1
index 248be70..4217870 100644
--- a/man/man1/gdal_translate.1
+++ b/man/man1/gdal_translate.1
@@ -1,8 +1,8 @@
-.TH "gdal_translate" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal_translate" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_translate \- .TH "gdal_translate" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal_translate \- .TH "gdal_translate" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_utilities.1 b/man/man1/gdal_utilities.1
index 703be2f..0b34f67 100644
--- a/man/man1/gdal_utilities.1
+++ b/man/man1/gdal_utilities.1
@@ -1,8 +1,8 @@
-.TH "gdal_utilities" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdal_utilities" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_utilities \- .TH "gdal_utilities" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdal_utilities \- .TH "gdal_utilities" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaladdo.1 b/man/man1/gdaladdo.1
index 5368acd..65aa395 100644
--- a/man/man1/gdaladdo.1
+++ b/man/man1/gdaladdo.1
@@ -1,8 +1,8 @@
-.TH "gdaladdo" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdaladdo" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdaladdo \- .TH "gdaladdo" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdaladdo \- .TH "gdaladdo" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalbuildvrt.1 b/man/man1/gdalbuildvrt.1
index 93efc68..1b7721b 100644
--- a/man/man1/gdalbuildvrt.1
+++ b/man/man1/gdalbuildvrt.1
@@ -1,8 +1,8 @@
-.TH "gdalbuildvrt" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdalbuildvrt" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalbuildvrt \- .TH "gdalbuildvrt" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdalbuildvrt \- .TH "gdalbuildvrt" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalcompare.1 b/man/man1/gdalcompare.1
index 63ced76..46d3245 100644
--- a/man/man1/gdalcompare.1
+++ b/man/man1/gdalcompare.1
@@ -1,8 +1,8 @@
-.TH "gdalcompare" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdalcompare" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalcompare \- .TH "gdalcompare" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdalcompare \- .TH "gdalcompare" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaldem.1 b/man/man1/gdaldem.1
index e640a70..3a36aae 100644
--- a/man/man1/gdaldem.1
+++ b/man/man1/gdaldem.1
@@ -1,8 +1,8 @@
-.TH "gdaldem" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdaldem" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdaldem \- .TH "gdaldem" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdaldem \- .TH "gdaldem" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalinfo.1 b/man/man1/gdalinfo.1
index 41b1649..2535790 100644
--- a/man/man1/gdalinfo.1
+++ b/man/man1/gdalinfo.1
@@ -1,8 +1,8 @@
-.TH "gdalinfo" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdalinfo" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalinfo \- .TH "gdalinfo" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdalinfo \- .TH "gdalinfo" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -12,7 +12,7 @@ gdalinfo \- lists information about a raster dataset
 .PP
 .nf
 
-gdalinfo [--help-general] [-mm] [-stats] [-hist] [-nogcp] [-nomd]
+gdalinfo [--help-general] [-json] [-mm] [-stats] [-hist] [-nogcp] [-nomd]
          [-norat] [-noct] [-nofl] [-checksum] [-proj4]
          [-listmdd] [-mdd domain|`all`]*
          [-sd subdataset] [-oo NAME=VALUE]* datasetname
@@ -21,6 +21,8 @@ gdalinfo [--help-general] [-mm] [-stats] [-hist] [-nogcp] [-nomd]
 .SH "DESCRIPTION"
 .PP
 The gdalinfo program lists various information about a GDAL supported raster dataset. 
+.IP "\fB\fB-json\fP\fP" 1c
+Display the output in json format. 
 .IP "\fB\fB-mm\fP\fP" 1c
 Force computation of the actual min/max values for each band in the dataset. 
 .IP "\fB\fB-stats\fP\fP" 1c
diff --git a/man/man1/gdallocationinfo.1 b/man/man1/gdallocationinfo.1
index c502fe3..a7b523b 100644
--- a/man/man1/gdallocationinfo.1
+++ b/man/man1/gdallocationinfo.1
@@ -1,8 +1,8 @@
-.TH "gdallocationinfo" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdallocationinfo" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdallocationinfo \- .TH "gdallocationinfo" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdallocationinfo \- .TH "gdallocationinfo" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalmanage.1 b/man/man1/gdalmanage.1
index 0615354..4f4fd5d 100644
--- a/man/man1/gdalmanage.1
+++ b/man/man1/gdalmanage.1
@@ -1,8 +1,8 @@
-.TH "gdalmanage" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdalmanage" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalmanage \- .TH "gdalmanage" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdalmanage \- .TH "gdalmanage" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalmove.1 b/man/man1/gdalmove.1
index cf9a2d3..dedde99 100644
--- a/man/man1/gdalmove.1
+++ b/man/man1/gdalmove.1
@@ -1,8 +1,8 @@
-.TH "gdalmove" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdalmove" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalmove \- .TH "gdalmove" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdalmove \- .TH "gdalmove" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalsrsinfo.1 b/man/man1/gdalsrsinfo.1
index 6f832f1..4d8977e 100644
--- a/man/man1/gdalsrsinfo.1
+++ b/man/man1/gdalsrsinfo.1
@@ -1,8 +1,8 @@
-.TH "gdalsrsinfo" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdalsrsinfo" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalsrsinfo \- .TH "gdalsrsinfo" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdalsrsinfo \- .TH "gdalsrsinfo" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaltindex.1 b/man/man1/gdaltindex.1
index a9fe903..15fa377 100644
--- a/man/man1/gdaltindex.1
+++ b/man/man1/gdaltindex.1
@@ -1,8 +1,8 @@
-.TH "gdaltindex" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdaltindex" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdaltindex \- .TH "gdaltindex" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdaltindex \- .TH "gdaltindex" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaltransform.1 b/man/man1/gdaltransform.1
index 8e58aef..5fc1fd7 100644
--- a/man/man1/gdaltransform.1
+++ b/man/man1/gdaltransform.1
@@ -1,8 +1,8 @@
-.TH "gdaltransform" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdaltransform" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdaltransform \- .TH "gdaltransform" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdaltransform \- .TH "gdaltransform" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalwarp.1 b/man/man1/gdalwarp.1
index 247cd13..7ce8fa8 100644
--- a/man/man1/gdalwarp.1
+++ b/man/man1/gdalwarp.1
@@ -1,8 +1,8 @@
-.TH "gdalwarp" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "gdalwarp" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalwarp \- .TH "gdalwarp" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+gdalwarp \- .TH "gdalwarp" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/nearblack.1 b/man/man1/nearblack.1
index 340300c..b68cbc9 100644
--- a/man/man1/nearblack.1
+++ b/man/man1/nearblack.1
@@ -1,8 +1,8 @@
-.TH "nearblack" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "nearblack" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-nearblack \- .TH "nearblack" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+nearblack \- .TH "nearblack" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogr2ogr.1 b/man/man1/ogr2ogr.1
index cefb0f5..dec78ca 100644
--- a/man/man1/ogr2ogr.1
+++ b/man/man1/ogr2ogr.1
@@ -1,8 +1,8 @@
-.TH "ogr2ogr" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "ogr2ogr" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ogr2ogr \- .TH "ogr2ogr" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+ogr2ogr \- .TH "ogr2ogr" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -119,7 +119,9 @@ Advanced options :
 .IP "\fB\fB-doo\fP \fINAME=VALUE\fP:\fP" 1c
 (starting with GDAL 2.0) Destination dataset open option (format specific), only valid in -update mode 
 .IP "\fB\fB-gt\fP \fIn\fP:\fP" 1c
-group \fIn\fP features per transaction (default 20000 in OGR 1.11, 200 in previous releases). Increase the value for better performance when writing into DBMS drivers that have transaction support. 
+group \fIn\fP features per transaction (default 20000 in OGR 1.11, 200 in previous releases). Increase the value for better performance when writing into DBMS drivers that have transaction support. Starting with GDAL 2.0, n can be set to unlimited to load the data into a single transaction. 
+.IP "\fB\fB-ds_transaction\fP:\fP" 1c
+(starting with GDAL 2.0) Force the use of a dataset level transaction (for drivers that support such mechanism), especially for drivers such as FileGDB that only support dataset level transaction in emulation mode. 
 .IP "\fB\fB-clipsrc\fP\fI [xmin ymin xmax ymax]|WKT|datasource|spat_extent\fP: \fP" 1c
 (starting with GDAL 1.7.0) clip geometries to the specified bounding box (expressed in source SRS), WKT geometry (POLYGON or MULTIPOLYGON), from a datasource or to the spatial extent of the \fB-spat\fP option if you use the \fIspat_extent\fP keyword. When specifying a datasource, you will generally want to use it in combination of the \fB-clipsrclayer\fP, \fB-clipsrcwhere\fP or \fB-clipsrcsql\fP options 
 .IP "\fB\fB-clipsrcsql\fP \fIsql_statement\fP:\fP" 1c
diff --git a/man/man1/ogr_utilities.1 b/man/man1/ogr_utilities.1
index 6b26a09..c86582d 100644
--- a/man/man1/ogr_utilities.1
+++ b/man/man1/ogr_utilities.1
@@ -1,8 +1,8 @@
-.TH "ogr_utilities" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "ogr_utilities" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ogr_utilities \- .TH "ogr_utilities" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+ogr_utilities \- .TH "ogr_utilities" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogrinfo.1 b/man/man1/ogrinfo.1
index 5a1e517..3844416 100644
--- a/man/man1/ogrinfo.1
+++ b/man/man1/ogrinfo.1
@@ -1,8 +1,8 @@
-.TH "ogrinfo" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "ogrinfo" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ogrinfo \- .TH "ogrinfo" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+ogrinfo \- .TH "ogrinfo" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogrlineref.1 b/man/man1/ogrlineref.1
index 2c3f82a..7ea8539 100644
--- a/man/man1/ogrlineref.1
+++ b/man/man1/ogrlineref.1
@@ -1,8 +1,8 @@
-.TH "ogrlineref" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "ogrlineref" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ogrlineref \- .TH "ogrlineref" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+ogrlineref \- .TH "ogrlineref" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogrtindex.1 b/man/man1/ogrtindex.1
index da86152..e8ce9c8 100644
--- a/man/man1/ogrtindex.1
+++ b/man/man1/ogrtindex.1
@@ -1,8 +1,8 @@
-.TH "ogrtindex" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "ogrtindex" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ogrtindex \- .TH "ogrtindex" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+ogrtindex \- .TH "ogrtindex" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/pct2rgb.1 b/man/man1/pct2rgb.1
index c5eee33..6755d7a 100644
--- a/man/man1/pct2rgb.1
+++ b/man/man1/pct2rgb.1
@@ -1,8 +1,8 @@
-.TH "pct2rgb" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "pct2rgb" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-pct2rgb \- .TH "pct2rgb" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+pct2rgb \- .TH "pct2rgb" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/rgb2pct.1 b/man/man1/rgb2pct.1
index eccbeb1..f2e4f9f 100644
--- a/man/man1/rgb2pct.1
+++ b/man/man1/rgb2pct.1
@@ -1,8 +1,8 @@
-.TH "rgb2pct" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+.TH "rgb2pct" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-rgb2pct \- .TH "rgb2pct" 1 "Mon May 4 2015" "GDAL" \" -*- nroff -*-
+rgb2pct \- .TH "rgb2pct" 1 "Mon May 25 2015" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/ogr/ogrsf_frmts/csv/drv_csv.html b/ogr/ogrsf_frmts/csv/drv_csv.html
index a358349..ff0352d 100644
--- a/ogr/ogrsf_frmts/csv/drv_csv.html
+++ b/ogr/ogrsf_frmts/csv/drv_csv.html
@@ -51,8 +51,8 @@ specifying the open options described in the below "Open options" section.</p>
 The attribute field values are separated by commas. At least two fields
 per line must be present. Lines may be terminated by a DOS (CR/LF) or
 Unix (LF) style line terminators. Each record should have the same number
-of fields. Starting with GDAL 1.7.0, the driver will also accept a semicolon
-or a tabulation character as field separator . This autodetection will work only
+of fields. The driver will also accept a semicolon, a tabulation or a space
+(GDAL >= 2.0 for the later) character as field separator . This autodetection will work only
 if there's no other potential separator on the first line of the CSV file.
 Otherwise it will default to comma as separator.</p>
 
@@ -147,6 +147,9 @@ OGRFeature(test):3
 Starting with GDAL 2.0, the following open options can be specified
 (typically with the -oo name=value parameters of ogrinfo or ogr2ogr):
 <ul>
+<li><b>MERGE_SEPARATOR</b>=YES/NO (defaults to NO). Setting it to YES will
+enable merging consecutive separators. Mostly usefull when it is the space
+character.</li>
 <li><b>AUTODETECT_TYPE</b>=YES/NO (defaults to NO). Setting it to YES will
 enable auto-detection of field data types. If while reading the records
 (beyond the records used for autodetection), a value is found to not correspond
@@ -195,7 +198,7 @@ columns in the csv file) by specifying GEOMETRY=<b>AS_XYZ</b>, GEOMETRY=<b>AS_XY
 The geometry column(s) will be prepended to the columns with the attributes values.</li><p>
 <li><b>CREATE_CSVT</b>=YES/NO (Starting with GDAL 1.7.0): Create the associated .csvt file (see above paragraph)
 to describe the type of each column of the layer and its optional width and precision. Default value : NO</li><p>
-<li><b>SEPARATOR</b>=COMMA/SEMICOLON/TAB (Starting with GDAL 1.7.0): Field separator character. Default value : COMMA</li><p>
+<li><b>SEPARATOR</b>=COMMA/SEMICOLON/TAB/SPACE (Starting with GDAL 1.7.0): Field separator character. Default value : COMMA</li><p>
 <li><b>WRITE_BOM</b>=YES/NO (Starting with GDAL >1.9.2): Write a UTF-8 Byte Order Mark (BOM) at the start of the file. Default value : NO</li><p>
 </ul>
 </p>
diff --git a/ogr/ogrsf_frmts/csv/ogr_csv.h b/ogr/ogrsf_frmts/csv/ogr_csv.h
index f136ed6..8e73dd3 100644
--- a/ogr/ogrsf_frmts/csv/ogr_csv.h
+++ b/ogr/ogrsf_frmts/csv/ogr_csv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_csv.h 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogr_csv.h 29237 2015-05-24 08:38:20Z rouault $
  *
  * Project:  CSV Translator
  * Purpose:  Definition of classes for OGR .csv driver.
@@ -46,7 +46,8 @@ class OGRCSVDataSource;
 
 char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter,
                              int bDontHonourStrings = FALSE,
-                             int bKeepLeadingAndClosingQuotes = FALSE);
+                             int bKeepLeadingAndClosingQuotes = FALSE,
+                             int bMergeDelimiter = FALSE);
 
 /************************************************************************/
 /*                             OGRCSVLayer                              */
@@ -97,6 +98,8 @@ class OGRCSVLayer : public OGRLayer
     int                 bWarningBadTypeOrWidth;
     int                 bKeepSourceColumns;
     
+    int                 bMergeDelimiter;
+    
     char              **GetNextLineTokens();
 
   public:
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp b/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
index 355bc66..db318ee 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcsvdatasource.cpp 27959 2014-11-14 18:29:21Z rouault $
+ * $Id: ogrcsvdatasource.cpp 29237 2015-05-24 08:38:20Z rouault $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVDataSource class
@@ -34,7 +34,7 @@
 #include "cpl_csv.h"
 #include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: ogrcsvdatasource.cpp 27959 2014-11-14 18:29:21Z rouault $");
+CPL_CVSID("$Id: ogrcsvdatasource.cpp 29237 2015-05-24 08:38:20Z rouault $");
 
 /************************************************************************/
 /*                          OGRCSVDataSource()                          */
@@ -408,6 +408,26 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
         return FALSE;
     }
     char chDelimiter = CSVDetectSeperator(pszLine);
+#if 0
+    const char *pszDelimiter = CSLFetchNameValueDef( papszOpenOptions, "SEPARATOR", "AUTO");
+    if( !EQUAL(pszDelimiter, "AUTO") )
+    {
+        if (EQUAL(pszDelimiter, "COMMA"))
+            chDelimiter = ',';
+        else if (EQUAL(pszDelimiter, "SEMICOLON"))
+            chDelimiter = ';';
+        else if (EQUAL(pszDelimiter, "TAB"))
+            chDelimiter = '\t';
+        else if (EQUAL(pszDelimiter, "SPACE"))
+            chDelimiter = ' ';
+        else
+        {
+            CPLError( CE_Warning, CPLE_AppDefined, 
+                  "SEPARATOR=%s not understood, use one of COMMA, SEMICOLON, SPACE or TAB.",
+                  pszDelimiter );
+        }
+    }
+#endif
 
     /* Force the delimiter to be TAB for a .tsv file that has a tabulation */
     /* in its first line */
@@ -546,10 +566,12 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
             chDelimiter = ';';
         else if (EQUAL(pszDelimiter, "TAB"))
             chDelimiter = '\t';
+        else if (EQUAL(pszDelimiter, "SPACE"))
+            chDelimiter = ' ';
         else
         {
             CPLError( CE_Warning, CPLE_AppDefined, 
-                  "SEPARATOR=%s not understood, use one of COMMA, SEMICOLON or TAB.",
+                  "SEPARATOR=%s not understood, use one of COMMA, SEMICOLON, SPACE or TAB.",
                   pszDelimiter );
         }
     }
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp b/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
index b3d316e..9044ee4 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcsvdriver.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrcsvdriver.cpp 29237 2015-05-24 08:38:20Z rouault $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVDriver.
@@ -31,7 +31,7 @@
 #include "ogr_csv.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrcsvdriver.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrcsvdriver.cpp 29237 2015-05-24 08:38:20Z rouault $");
 
 /************************************************************************/
 /*                         OGRCSVDriverIdentify()                       */
@@ -252,6 +252,7 @@ void RegisterOGRCSV()
 "    <Value>COMMA</Value>"
 "    <Value>SEMICOLON</Value>"
 "    <Value>TAB</Value>"
+"    <Value>SPACE</Value>"
 "  </Option>"
 #ifdef WIN32
 "  <Option name='LINEFORMAT' type='string-select' description='end-of-line sequence' default='CRLF'>"
@@ -273,6 +274,16 @@ void RegisterOGRCSV()
 
         poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
+#if 0
+"  <Option name='SEPARATOR' type='string-select' description='field separator' default='AUTO'>"
+"    <Value>AUTO</Value>"
+"    <Value>COMMA</Value>"
+"    <Value>SEMICOLON</Value>"
+"    <Value>TAB</Value>"
+"    <Value>SPACE</Value>"
+"  </Option>"
+#endif
+"  <Option name='MERGE_SEPARATOR' type='boolean' description='whether to merge consecutive separators' default='NO'/>"
 "  <Option name='AUTODETECT_TYPE' type='boolean' description='whether to guess data type from first bytes of the file' default='NO'/>"
 "  <Option name='KEEP_SOURCE_COLUMNS' type='boolean' description='whether to add original columns whose guessed data type is not String. Only used if AUTODETECT_TYPE=YES' default='NO'/>"
 "  <Option name='AUTODETECT_WIDTH' type='string-select' description='whether to auto-detect width/precision. Only used if AUTODETECT_TYPE=YES' default='NO'>"
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp b/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
index 270f305..74ffde1 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrcsvlayer.cpp 28831 2015-04-01 16:46:05Z rouault $
+ * $Id: ogrcsvlayer.cpp 29237 2015-05-24 08:38:20Z rouault $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVLayer class.
@@ -34,7 +34,7 @@
 #include "cpl_csv.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrcsvlayer.cpp 28831 2015-04-01 16:46:05Z rouault $");
+CPL_CVSID("$Id: ogrcsvlayer.cpp 29237 2015-05-24 08:38:20Z rouault $");
 
 
 
@@ -48,7 +48,8 @@ CPL_CVSID("$Id: ogrcsvlayer.cpp 28831 2015-04-01 16:46:05Z rouault $");
 /************************************************************************/
 
 static char **CSVSplitLine( const char *pszString, char chDelimiter,
-                            int bKeepLeadingAndClosingQuotes )
+                            int bKeepLeadingAndClosingQuotes,
+                            int bMergeDelimiter )
 
 {
     char        **papszRetList = NULL;
@@ -72,6 +73,11 @@ static char **CSVSplitLine( const char *pszString, char chDelimiter,
             if( !bInString && *pszString == chDelimiter )
             {
                 pszString++;
+                if( bMergeDelimiter )
+                {
+                    while( *pszString == chDelimiter )
+                        pszString ++;
+                }
                 break;
             }
 
@@ -128,7 +134,8 @@ static char **CSVSplitLine( const char *pszString, char chDelimiter,
 
 char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter,
                              int bDontHonourStrings,
-                             int bKeepLeadingAndClosingQuotes )
+                             int bKeepLeadingAndClosingQuotes,
+                             int bMergeDelimiter )
 
 {
     const char  *pszLine;
@@ -155,7 +162,8 @@ char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter,
 /*      Parse, and return tokens.                                       */
 /* -------------------------------------------------------------------- */
     if( strchr(pszLine,'\"') == NULL )
-        return CSVSplitLine( pszLine, chDelimiter, bKeepLeadingAndClosingQuotes );
+        return CSVSplitLine( pszLine, chDelimiter, bKeepLeadingAndClosingQuotes,
+                             bMergeDelimiter );
 
 /* -------------------------------------------------------------------- */
 /*      We must now count the quotes in our working string, and as      */
@@ -195,7 +203,8 @@ char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter,
         nWorkLineLength += nLineLen + 1;
     }
 
-    papszReturn = CSVSplitLine( pszWorkLine, chDelimiter, bKeepLeadingAndClosingQuotes );
+    papszReturn = CSVSplitLine( pszWorkLine, chDelimiter,
+                                bKeepLeadingAndClosingQuotes, bMergeDelimiter );
 
     CPLFree( pszWorkLine );
 
@@ -250,6 +259,8 @@ OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn,
     nTotalFeatures = -1;
     bWarningBadTypeOrWidth = FALSE;
     bKeepSourceColumns = FALSE;
+    
+    bMergeDelimiter = FALSE;
 }
 
 /************************************************************************/
@@ -261,6 +272,8 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
                                     char** papszOpenOptions )
 {
 
+    bMergeDelimiter = CSLFetchBoolean(papszOpenOptions, "MERGE_SEPARATOR", FALSE);
+
 /* -------------------------------------------------------------------- */
 /*      If this is not a new file, read ahead to establish if it is     */
 /*      already in CRLF (DOS) mode, or just a normal unix CR mode.      */
@@ -339,9 +352,10 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
             /* tokenize without quotes to get the actual values */
             CSLDestroy( papszTokens );
             // papszTokens = OGRCSVReadParseLineL( fpCSV, chDelimiter, FALSE );   
-            papszTokens = CSLTokenizeString2( pszLine, szDelimiter, 
-                                              (CSLT_HONOURSTRINGS |
-                                               CSLT_ALLOWEMPTYTOKENS));
+            int nFlags = CSLT_HONOURSTRINGS;
+            if( !bMergeDelimiter )
+                nFlags |= CSLT_ALLOWEMPTYTOKENS;
+            papszTokens = CSLTokenizeString2( pszLine, szDelimiter,  nFlags );
             nFieldCount = CSLCount( papszTokens );
         }
     }
@@ -427,7 +441,7 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
         CPLFree(fname);
         if (fpCSVT!=NULL) {
             VSIRewindL(fpCSVT);
-            papszFieldTypes = OGRCSVReadParseLineL(fpCSVT, ',', FALSE);
+            papszFieldTypes = OGRCSVReadParseLineL(fpCSVT, ',', FALSE,FALSE);
             VSIFCloseL(fpCSVT);
         }
     }
@@ -762,7 +776,8 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
         while( !VSIFEofL(fpMem) )
         {
             char** papszTokens = OGRCSVReadParseLineL( fpMem, chDelimiter, FALSE,
-                                                       bQuotedFieldAsString );
+                                                       bQuotedFieldAsString,
+                                                       bMergeDelimiter );
             /* Can happen if we just reach EOF while trying to read new bytes */
             if( papszTokens == NULL )
                 break;
@@ -1052,7 +1067,8 @@ char** OGRCSVLayer::GetNextLineTokens()
 
     while(TRUE)
     {
-        papszTokens = OGRCSVReadParseLineL( fpCSV, chDelimiter, bDontHonourStrings );
+        papszTokens = OGRCSVReadParseLineL( fpCSV, chDelimiter, bDontHonourStrings,
+                                            FALSE, bMergeDelimiter );
         if( papszTokens == NULL )
             return NULL;
 
@@ -1638,7 +1654,17 @@ OGRErr OGRCSVLayer::WriteHeader()
                 CPLEscapeString( poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), 
                                  -1, CPLES_CSV );
 
-            if (fpCSV) VSIFPrintfL( fpCSV, "%s", pszEscaped );
+            if (fpCSV)
+            {
+                int bAddDoubleQuote = FALSE;
+                if( chDelimiter == ' ' && pszEscaped[0] != '"' && strchr(pszEscaped, ' ') != NULL )
+                    bAddDoubleQuote = TRUE;
+                if( bAddDoubleQuote )
+                    VSIFWriteL( "\"", 1, 1, fpCSV );
+                VSIFPrintfL( fpCSV, "%s", pszEscaped );
+                if( bAddDoubleQuote )
+                    VSIFWriteL( "\"", 1, 1, fpCSV );
+            }
             CPLFree( pszEscaped );
 
             if (fpCSVT)
@@ -1882,7 +1908,14 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
 
         int nLen = (int)strlen(pszEscaped);
         bNonEmptyLine |= (nLen != 0);
+        int bAddDoubleQuote = FALSE;
+        if( chDelimiter == ' ' && pszEscaped[0] != '"' && strchr(pszEscaped, ' ') != NULL )
+            bAddDoubleQuote = TRUE;
+        if( bAddDoubleQuote )
+            VSIFWriteL( "\"", 1, 1, fpCSV );
         VSIFWriteL( pszEscaped, 1, nLen, fpCSV );
+        if( bAddDoubleQuote )
+            VSIFWriteL( "\"", 1, 1, fpCSV );
         CPLFree( pszEscaped );
     }
 
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp b/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp
index f8742c3..be0d464 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: FGdbDatasource.cpp 28601 2015-03-03 11:06:40Z rouault $
+ * $Id: FGdbDatasource.cpp 29196 2015-05-14 15:50:13Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements FileGDB OGR Datasource.
@@ -37,7 +37,7 @@
 #include "FGdbUtils.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: FGdbDatasource.cpp 28601 2015-03-03 11:06:40Z rouault $");
+CPL_CVSID("$Id: FGdbDatasource.cpp 29196 2015-05-14 15:50:13Z rouault $");
 
 using std::vector;
 using std::wstring;
@@ -430,6 +430,12 @@ OGRLayer * FGdbDataSource::ExecuteSQL( const char *pszSQLCommand,
                                        const char *pszDialect )
 
 {
+    size_t count = m_layers.size();
+    for(size_t i = 0; i < count; ++i )
+    {
+        m_layers[i]->EndBulkLoad();
+    }
+    
 /* -------------------------------------------------------------------- */
 /*      Use generic implementation for recognized dialects              */
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp b/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp
index 62cf72f..0c63ebc 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: FGdbDriver.cpp 28601 2015-03-03 11:06:40Z rouault $
+ * $Id: FGdbDriver.cpp 29180 2015-05-10 15:07:48Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements FileGDB OGR driver.
@@ -36,7 +36,7 @@
 #include "cpl_multiproc.h"
 #include "ogrmutexeddatasource.h"
 
-CPL_CVSID("$Id: FGdbDriver.cpp 28601 2015-03-03 11:06:40Z rouault $");
+CPL_CVSID("$Id: FGdbDriver.cpp 29180 2015-05-10 15:07:48Z rouault $");
 
 extern "C" void RegisterOGRFileGDB();
 
@@ -278,30 +278,35 @@ OGRErr FGdbDriver::StartTransaction(OGRDataSource*& poDSInOut, int& bOutHasReope
     delete pConnection->m_pGeodatabase;
     pConnection->m_pGeodatabase = NULL;
 
-    CPLString osBackupName(osName);
-    osBackupName += ".ogrbak";
+    CPLString osEditedName(osName);
+    osEditedName += ".ogredited";
 
     CPLPushErrorHandler(CPLQuietErrorHandler);
-    CPLUnlinkTree(osBackupName);
+    CPLUnlinkTree(osEditedName);
     CPLPopErrorHandler();
 
     OGRErr eErr = OGRERR_NONE;
+    CPLString osDatabaseToReopen;
     if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") ||
-        CPLCopyTree( osBackupName, osName ) != 0 )
+        CPLCopyTree( osEditedName, osName ) != 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot backup geodatabase");
         eErr = OGRERR_FAILURE;
+        osDatabaseToReopen = osName;
     }
+    else
+        osDatabaseToReopen = osEditedName;
 
     pConnection->m_pGeodatabase = new Geodatabase;
-    long hr = ::OpenGeodatabase(StringToWString(osName), *(pConnection->m_pGeodatabase));
+    long hr = ::OpenGeodatabase(StringToWString(osDatabaseToReopen), *(pConnection->m_pGeodatabase));
     if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || FAILED(hr))
     {
         delete pConnection->m_pGeodatabase;
         pConnection->m_pGeodatabase = NULL;
         Release(osName);
-        GDBErr(hr, "Failed to re-open Geodatabase. Dataset should be closed");
+        GDBErr(hr, CPLSPrintf("Failed to open %s. Dataset should be closed",
+                              osDatabaseToReopen.c_str()));
 
         return OGRERR_FAILURE;
     }
@@ -325,6 +330,7 @@ OGRErr FGdbDriver::CommitTransaction(OGRDataSource*& poDSInOut, int& bOutHasReop
 
     bOutHasReopenedDS = FALSE;
 
+
     OGRMutexedDataSource* poMutexedDS = (OGRMutexedDataSource*)poDSInOut;
     FGdbDataSource* poDS = (FGdbDataSource* )poMutexedDS->GetBaseDataSource();
     FGdbDatabaseConnection* pConnection = poDS->GetConnection();
@@ -335,17 +341,81 @@ OGRErr FGdbDriver::CommitTransaction(OGRDataSource*& poDSInOut, int& bOutHasReop
         return OGRERR_FAILURE;
     }
 
+    bOutHasReopenedDS = TRUE;
+
     CPLString osName(poMutexedDS->GetName());
     if( osName[osName.size()-1] == '/' || osName[osName.size()-1] == '\\' )
         osName.resize(osName.size()-1);
 
-    CPLString osBackupName(osName);
-    osBackupName += ".ogrbak";
-    CPLPushErrorHandler(CPLQuietErrorHandler);
-    CPLUnlinkTree(osBackupName);
-    CPLPopErrorHandler();
+    pConnection->m_nRefCount ++;
+    delete poDSInOut;
+    poDSInOut = NULL;
+    poMutexedDS = NULL;
+    poDS = NULL;
+
+    ::CloseGeodatabase(*(pConnection->m_pGeodatabase));
+    delete pConnection->m_pGeodatabase;
+    pConnection->m_pGeodatabase = NULL;
+
+    CPLString osEditedName(osName);
+    osEditedName += ".ogredited";
+    CPLString osTmpName(osName);
+    osTmpName += ".ogrtmp";
+    
+    /* Install the backup copy as the main database in 3 steps : */
+    /* first rename the main directory  in .tmp */
+    /* then rename the edited copy under regular name */
+    /* and finally dispose the .tmp directory */
+    /* That way there's no risk definitely losing data */
+    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || 
+        VSIRename(osName, osTmpName) != 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot rename %s to %s. Edited database during transaction is in %s"
+                 "Dataset should be closed",
+                 osName.c_str(), osTmpName.c_str(), osEditedName.c_str());
+        pConnection->SetLocked(FALSE);
+        Release(osName);
+        return OGRERR_FAILURE;
+    }
+    
+    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || 
+        VSIRename(osEditedName, osName) != 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot rename %s to %s. The original geodatabase is in '%s'. "
+                 "Dataset should be closed",
+                 osEditedName.c_str(), osName.c_str(), osTmpName.c_str());
+        pConnection->SetLocked(FALSE);
+        Release(osName);
+        return OGRERR_FAILURE;
+    }
+
+    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE3") || 
+        CPLUnlinkTree(osTmpName) != 0 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Cannot remove %s. Manual cleanup required", osTmpName.c_str());
+    }
+
+    pConnection->m_pGeodatabase = new Geodatabase;
+    long hr = ::OpenGeodatabase(StringToWString(osName), *(pConnection->m_pGeodatabase));
+    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE4") || FAILED(hr))
+    {
+        delete pConnection->m_pGeodatabase;
+        pConnection->m_pGeodatabase = NULL;
+        pConnection->SetLocked(FALSE);
+        Release(osName);
+        GDBErr(hr, "Failed to re-open Geodatabase. Dataset should be closed");
+        return OGRERR_FAILURE;
+    }
+
+    FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
+    pDS->Open(osName, TRUE);
+    poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);
 
     pConnection->SetLocked(FALSE);
+
     return OGRERR_NONE;
 }
 
@@ -369,8 +439,6 @@ OGRErr FGdbDriver::RollbackTransaction(OGRDataSource*& poDSInOut, int& bOutHasRe
         return OGRERR_FAILURE;
     }
 
-    pConnection->SetLocked(FALSE);
-
     bOutHasReopenedDS = TRUE;
 
     CPLString osName(poMutexedDS->GetName());
@@ -387,52 +455,26 @@ OGRErr FGdbDriver::RollbackTransaction(OGRDataSource*& poDSInOut, int& bOutHasRe
     delete pConnection->m_pGeodatabase;
     pConnection->m_pGeodatabase = NULL;
 
-    CPLString osBackupName(osName);
-    osBackupName += ".ogrbak";
-    CPLString osTmpName(osName);
-    osTmpName += ".ogrtmp";
-    
-    /* Restore the backup copy in 3 steps : */
-    /* first rename the active directory (the one that we want to discard) in .tmp */
-    /* then rename the backup copy (the one we want to restore) under regular name */
-    /* and finally dispose the .tmp directory */
-    /* That way there's no risk definitely losing data */
-    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || 
-        VSIRename(osName, osTmpName) != 0 )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot rename %s to %s. The original geodatabase is supposed to be in '%s'. "
-                 "Dataset should be closed",
-                 osName.c_str(), osTmpName.c_str(), osBackupName.c_str());
-        Release(osName);
-        return OGRERR_FAILURE;
-    }
-    
-    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || 
-        VSIRename(osBackupName, osName) != 0 )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot rename %s to %s. The original geodatabase is supposed to be in '%s'. "
-                 "Dataset should be closed",
-                 osBackupName.c_str(), osName.c_str(), osBackupName.c_str());
-        Release(osName);
-        return OGRERR_FAILURE;
-    }
+    CPLString osEditedName(osName);
+    osEditedName += ".ogredited";
 
-    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE3") || 
-        CPLUnlinkTree(osTmpName) != 0 )
+    OGRErr eErr = OGRERR_NONE;
+    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || 
+        CPLUnlinkTree(osEditedName) != 0 )
     {
         CPLError(CE_Warning, CPLE_AppDefined,
-                 "Cannot remove %s. Manual cleanup required", osTmpName.c_str());
+                 "Cannot remove %s. Manual cleanup required", osEditedName.c_str());
+        eErr = OGRERR_FAILURE;
     }
 
     pConnection->m_pGeodatabase = new Geodatabase;
     long hr = ::OpenGeodatabase(StringToWString(osName), *(pConnection->m_pGeodatabase));
-    if (EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE4") ||
+    if (EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") ||
         FAILED(hr))
     {
         delete pConnection->m_pGeodatabase;
         pConnection->m_pGeodatabase = NULL;
+        pConnection->SetLocked(FALSE);
         Release(osName);
         GDBErr(hr, "Failed to re-open Geodatabase. Dataset should be closed");
         return OGRERR_FAILURE;
@@ -442,19 +484,9 @@ OGRErr FGdbDriver::RollbackTransaction(OGRDataSource*& poDSInOut, int& bOutHasRe
     pDS->Open(osName, TRUE);
     poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);
 
-    return OGRERR_NONE;
-}
-
-/***********************************************************************/
-/*                       ReadoptOldFeatureDefn()                       */
-/***********************************************************************/
+    pConnection->SetLocked(FALSE);
 
-void FGdbDriver::ReadoptOldFeatureDefn(CPL_UNUSED OGRDataSource* poDS,
-                                       OGRLayer* poLayer,
-                                       OGRFeatureDefn* poFeatureDefn)
-{
-    FGdbLayer* poFGdbLayer = (FGdbLayer* )((OGRMutexedLayer*)poLayer)->GetBaseLayer();
-    poFGdbLayer->ReadoptOldFeatureDefn(poFeatureDefn);
+    return eErr;
 }
 
 /***********************************************************************/
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp b/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp
index 0d5c8f6..1e3b6f2 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
-* $Id: FGdbLayer.cpp 29119 2015-05-02 21:38:04Z rouault $
+* $Id: FGdbLayer.cpp 29196 2015-05-14 15:50:13Z rouault $
 *
 * Project:  OpenGIS Simple Features Reference Implementation
 * Purpose:  Implements FileGDB OGR layer.
@@ -37,7 +37,7 @@
 #include "FGdbUtils.h"
 #include "cpl_minixml.h" // the only way right now to extract schema information
 
-CPL_CVSID("$Id: FGdbLayer.cpp 29119 2015-05-02 21:38:04Z rouault $");
+CPL_CVSID("$Id: FGdbLayer.cpp 29196 2015-05-14 15:50:13Z rouault $");
 
 using std::string;
 using std::wstring;
@@ -1676,6 +1676,9 @@ bool FGdbLayer::Create(FGdbDataSource* pParentDataSource,
 
     m_papszOptions = CSLDuplicate(papszOptions);
     m_bCreateMultipatch = CSLTestBoolean(CSLFetchNameValueDef(m_papszOptions, "CREATE_MULTIPATCH", "NO"));
+    
+    // Default to YES here assuming ogr2ogr scenario
+    m_bBulkLoadAllowed = CSLTestBoolean(CPLGetConfigOption("FGDB_BULK_LOAD", "YES"));
 
     /* Store the new FGDB Table pointer and set up the OGRFeatureDefn */
     return FGdbLayer::Initialize(pParentDataSource, table, wtable_path, L"Table");
@@ -2864,14 +2867,3 @@ int FGdbLayer::TestCapability( const char* pszCap )
         return FALSE;
 }
 
-/************************************************************************/
-/*                       ReadoptOldFeatureDefn()                        */
-/************************************************************************/
-
-void FGdbLayer::ReadoptOldFeatureDefn(OGRFeatureDefn* poFeatureDefn)
-{
-    CPLAssert(m_pFeatureDefn->IsSame(poFeatureDefn));
-    m_pFeatureDefn->Release();
-    m_pFeatureDefn = poFeatureDefn;
-    m_pFeatureDefn->Reference();
-}
diff --git a/ogr/ogrsf_frmts/filegdb/drv_filegdb.html b/ogr/ogrsf_frmts/filegdb/drv_filegdb.html
index 149d8a8..17a13a8 100644
--- a/ogr/ogrsf_frmts/filegdb/drv_filegdb.html
+++ b/ogr/ogrsf_frmts/filegdb/drv_filegdb.html
@@ -26,7 +26,9 @@ i.e. not depending on a third-party library) read-only driver.</p>
 The FGDB_BULK_LOAD configuration option can be set to YES to speed-up feature insertion (or sometimes solve problems
 when inserting a lot of features (see http://trac.osgeo.org/gdal/ticket/4420). The effect of this configuration option
 is to cause a write lock to be taken and a temporary disabling of the indexes. Those are restored when the datasource is
-closed or when a read operation is done.
+closed or when a read operation is done.<p>
+
+Starting with GDAL 2.0, bulk load is enabled by default for newly created layers (unless otherwise specified).
 
 <h2>SQL support (OGR >= 1.10)</h2>
 
diff --git a/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h b/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h
index 3c4536d..2cced8d 100644
--- a/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h
+++ b/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h
@@ -1,5 +1,5 @@
 /******************************************************************************
-* $Id: ogr_fgdb.h 28601 2015-03-03 11:06:40Z rouault $
+* $Id: ogr_fgdb.h 29196 2015-05-14 15:50:13Z rouault $
 *
 * Project:  OpenGIS Simple Features Reference Implementation
 * Purpose:  Standard includes and class definitions ArcObjects OGR driver.
@@ -99,6 +99,8 @@ class FGdbDataSource;
 
 class FGdbLayer : public FGdbBaseLayer
 {
+  friend class FGdbDataSource;
+
   int                 m_bBulkLoadAllowed;
   int                 m_bBulkLoadInProgress;
 
@@ -177,8 +179,6 @@ public:
   OGRErr              GetLayerXML ( char **poXml );
   OGRErr              GetLayerMetadataXML ( char **poXmlMeta );
   
-  void                ReadoptOldFeatureDefn(OGRFeatureDefn* poFeatureDefn);
-  
 protected:
 
   bool GDBToOGRFields(CPLXMLNode* psFields);  
@@ -323,7 +323,6 @@ public:
   virtual OGRErr StartTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS);
   virtual OGRErr CommitTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS);
   virtual OGRErr RollbackTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS);
-  virtual void   ReadoptOldFeatureDefn(OGRDataSource* poDS, OGRLayer* poLayer, OGRFeatureDefn* poFeatureDefn);
 
   void Release(const char* pszName);
   CPLMutex* GetMutex() { return hMutex; }
diff --git a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp b/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp
index 0217de0..e60fc7a 100644
--- a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp
+++ b/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp
@@ -58,6 +58,15 @@ class OGRLayerWithTransaction: public OGRLayerDecorator
     virtual OGRErr      DeleteField( int iField );
     virtual OGRErr      ReorderFields( int* panMap );
     virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
+
+    virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poField,
+                                     int bApproxOK = TRUE );
+
+    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetFeature( GIntBig nFID );
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+  
 };
 
 
@@ -214,25 +223,8 @@ void OGRDataSourceWithTransaction::RemapLayers()
             poWrappedLayer->m_poDecoratedLayer = NULL;
         else
         {
-            OGRFeatureDefn* poOldFeatureDefn = poWrappedLayer->m_poFeatureDefn;
             poWrappedLayer->m_poDecoratedLayer =
                 m_poBaseDataSource->GetLayerByName(poWrappedLayer->GetName());
-            if( poOldFeatureDefn != NULL )
-            {
-                if( poWrappedLayer->m_poDecoratedLayer != NULL )
-                {
-#ifdef DEBUG
-                    int nRefCount = poOldFeatureDefn->GetReferenceCount();
-#endif
-                    m_poTransactionBehaviour->ReadoptOldFeatureDefn(m_poBaseDataSource,
-                                                                    poWrappedLayer->m_poDecoratedLayer,
-                                                                    poOldFeatureDefn);
-#ifdef DEBUG
-                    CPLAssert(poWrappedLayer->m_poDecoratedLayer->GetLayerDefn() == poOldFeatureDefn);
-                    CPLAssert(poOldFeatureDefn->GetReferenceCount() == nRefCount + 1 );
-#endif
-                }
-            }
         }
     }
     m_oMapLayers.clear();
@@ -494,11 +486,11 @@ OGRFeatureDefn *OGRLayerWithTransaction::GetLayerDefn()
         }
         return m_poFeatureDefn;
     }
-    if( m_poFeatureDefn == NULL )
+    else if( m_poFeatureDefn == NULL )
     {
-        m_poFeatureDefn = m_poDecoratedLayer->GetLayerDefn();
-        if( m_poFeatureDefn )
-            m_poFeatureDefn->Reference();
+        OGRFeatureDefn* poSrcFeatureDefn = m_poDecoratedLayer->GetLayerDefn();
+        m_poFeatureDefn = poSrcFeatureDefn->Clone();
+        m_poFeatureDefn->Reference();
     }
     return m_poFeatureDefn;
 }
@@ -507,37 +499,44 @@ OGRErr      OGRLayerWithTransaction::CreateField( OGRFieldDefn *poField,
                                             int bApproxOK )
 {
     if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
-    if( m_poFeatureDefn != NULL && m_poDS->IsInTransaction() )
+    int nFields = m_poDecoratedLayer->GetLayerDefn()->GetFieldCount();
+    OGRErr eErr = m_poDecoratedLayer->CreateField(poField, bApproxOK);
+    if( m_poFeatureDefn && eErr == OGRERR_NONE && m_poDecoratedLayer->GetLayerDefn()->GetFieldCount() == nFields + 1 )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Layer structural changes not allowed within emulated transaction");
-        return OGRERR_FAILURE;
+        m_poFeatureDefn->AddFieldDefn( m_poDecoratedLayer->GetLayerDefn()->GetFieldDefn(nFields) );
     }
-    return m_poDecoratedLayer->CreateField(poField, bApproxOK);
+    return eErr;
 }
 
-OGRErr      OGRLayerWithTransaction::DeleteField( int iField )
+OGRErr      OGRLayerWithTransaction::CreateGeomField( OGRGeomFieldDefn *poField,
+                                            int bApproxOK )
 {
     if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
-    if( m_poFeatureDefn != NULL && m_poDS->IsInTransaction() )
+    int nFields = m_poDecoratedLayer->GetLayerDefn()->GetGeomFieldCount();
+    OGRErr eErr = m_poDecoratedLayer->CreateGeomField(poField, bApproxOK);
+    if( m_poFeatureDefn && eErr == OGRERR_NONE && m_poDecoratedLayer->GetLayerDefn()->GetGeomFieldCount() == nFields + 1 )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Layer structural changes not allowed within emulated transaction");
-        return OGRERR_FAILURE;
+        m_poFeatureDefn->AddGeomFieldDefn( m_poDecoratedLayer->GetLayerDefn()->GetGeomFieldDefn(nFields) );
     }
-    return m_poDecoratedLayer->DeleteField(iField);
+    return eErr;
+}
+
+OGRErr      OGRLayerWithTransaction::DeleteField( int iField )
+{
+    if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
+    OGRErr eErr = m_poDecoratedLayer->DeleteField(iField);
+    if( m_poFeatureDefn && eErr == OGRERR_NONE )
+        m_poFeatureDefn->DeleteFieldDefn(iField);
+    return eErr;
 }
 
 OGRErr      OGRLayerWithTransaction::ReorderFields( int* panMap )
 {
     if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
-    if( m_poFeatureDefn != NULL && m_poDS->IsInTransaction() )
-    {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Layer structural changes not allowed within emulated transaction");
-        return OGRERR_FAILURE;
-    }
-    return m_poDecoratedLayer->ReorderFields(panMap);
+    OGRErr eErr = m_poDecoratedLayer->ReorderFields(panMap);
+    if( m_poFeatureDefn && eErr == OGRERR_NONE )
+        m_poFeatureDefn->ReorderFieldDefns(panMap);
+    return eErr;
 }
 
 OGRErr      OGRLayerWithTransaction::AlterFieldDefn( int iField,
@@ -545,12 +544,68 @@ OGRErr      OGRLayerWithTransaction::AlterFieldDefn( int iField,
                                                      int nFlags )
 {
     if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
-    if( m_poFeatureDefn != NULL && m_poDS->IsInTransaction() )
+    OGRErr eErr = m_poDecoratedLayer->AlterFieldDefn(iField, poNewFieldDefn, nFlags);
+    if( m_poFeatureDefn && eErr == OGRERR_NONE )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Layer structural changes not allowed within emulated transaction");
-        return OGRERR_FAILURE;
+        OGRFieldDefn* poSrcFieldDefn = m_poDecoratedLayer->GetLayerDefn()->GetFieldDefn(iField);
+        OGRFieldDefn* poDstFieldDefn = m_poFeatureDefn->GetFieldDefn(iField);
+        poDstFieldDefn->SetName(poSrcFieldDefn->GetNameRef());
+        poDstFieldDefn->SetType(poSrcFieldDefn->GetType());
+        poDstFieldDefn->SetSubType(poSrcFieldDefn->GetSubType());
+        poDstFieldDefn->SetWidth(poSrcFieldDefn->GetWidth());
+        poDstFieldDefn->SetPrecision(poSrcFieldDefn->GetPrecision());
+        poDstFieldDefn->SetDefault(poSrcFieldDefn->GetDefault());
+        poDstFieldDefn->SetNullable(poSrcFieldDefn->IsNullable());
     }
-    return m_poDecoratedLayer->AlterFieldDefn(iField, poNewFieldDefn, nFlags);
+    return eErr;
+}
+
+OGRFeature * OGRLayerWithTransaction::GetNextFeature()
+{
+    if( !m_poDecoratedLayer ) return NULL;
+    OGRFeature* poSrcFeature = m_poDecoratedLayer->GetNextFeature();
+    if( !poSrcFeature )
+        return NULL;
+    OGRFeature* poFeature = new OGRFeature(GetLayerDefn());
+    poFeature->SetFrom(poSrcFeature);
+    poFeature->SetFID(poSrcFeature->GetFID());
+    delete poSrcFeature;
+    return poFeature;
+}
+
+OGRFeature * OGRLayerWithTransaction::GetFeature( GIntBig nFID )
+{
+    if( !m_poDecoratedLayer ) return NULL;
+    OGRFeature* poSrcFeature = m_poDecoratedLayer->GetFeature(nFID);
+    if( !poSrcFeature )
+        return NULL;
+    OGRFeature* poFeature = new OGRFeature(GetLayerDefn());
+    poFeature->SetFrom(poSrcFeature);
+    poFeature->SetFID(poSrcFeature->GetFID());
+    delete poSrcFeature;
+    return poFeature;
+}
+
+OGRErr       OGRLayerWithTransaction::ISetFeature( OGRFeature *poFeature )
+{
+    if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
+    OGRFeature* poSrcFeature = new OGRFeature(m_poDecoratedLayer->GetLayerDefn());
+    poSrcFeature->SetFrom(poFeature);
+    poSrcFeature->SetFID(poFeature->GetFID());
+    OGRErr eErr = m_poDecoratedLayer->SetFeature(poSrcFeature);
+    delete poSrcFeature;
+    return eErr;
+}
+
+OGRErr       OGRLayerWithTransaction::ICreateFeature( OGRFeature *poFeature )
+{
+    if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
+    OGRFeature* poSrcFeature = new OGRFeature(m_poDecoratedLayer->GetLayerDefn());
+    poSrcFeature->SetFrom(poFeature);
+    poSrcFeature->SetFID(poFeature->GetFID());
+    OGRErr eErr = m_poDecoratedLayer->CreateFeature(poSrcFeature);
+    poFeature->SetFID(poSrcFeature->GetFID());
+    delete poSrcFeature;
+    return eErr;
 }
 
diff --git a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h b/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h
index 0127251..d0477c1 100644
--- a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h
+++ b/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h
@@ -89,26 +89,6 @@ class CPL_DLL IOGRTransactionBehaviour
         */
        virtual OGRErr RollbackTransaction(OGRDataSource*& poDSInOut,
                                           int& bOutHasReopenedDS) = 0;
-
-        /** Ask a layer to re-"adopt" its previous feature definition object.
-        *
-        * The aim is that the user doesn't see visible object changes.
-        *
-        * This method is called if StartTransaction(), CommitTransaction() or
-        * RollbackTransaction() has closed and reopened a datasource.
-        *
-        * The implementation os the method should drop the reference to feature
-        * definition object it may have currently, assign the poFeatureDefn as
-        * its current definition object, and take a new reference on it.
-        *
-        * The passed poFeatureDefn object is supposed to be the "same" as
-        * the one the layer has currently (as verified with IsSame()) since
-        * the emulated datasource wrapper prevents layer structural modifications
-        * in cases where the user has already called GetLayerDefn()
-        */
-        virtual void   ReadoptOldFeatureDefn(OGRDataSource* poDS,
-                                            OGRLayer* poLayer,
-                                            OGRFeatureDefn* poFeatureDefn) = 0;    
 };
 
 
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_object.h b/ogr/ogrsf_frmts/geojson/libjson/json_object.h
index 05b73b9..3875805 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/json_object.h
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_object.h
@@ -14,6 +14,7 @@
 #define _json_object_h_
 
 #include "symbol_renames.h"
+#include "cpl_port.h"
 
 #include "json_inttypes.h"
 
@@ -120,7 +121,7 @@ extern struct json_object* json_object_get(struct json_object *obj);
  * @param obj the json_object instance
  * @returns 1 if the object was freed.
  */
-int json_object_put(struct json_object *obj);
+int CPL_DLL json_object_put(struct json_object *obj);
 
 /**
  * Check if the json_object is of a given type
@@ -165,7 +166,7 @@ extern const char* json_object_to_json_string(struct json_object *obj);
  * @param flags formatting options, see JSON_C_TO_STRING_PRETTY and other constants
  * @returns a string in JSON format
  */
-extern const char* json_object_to_json_string_ext(struct json_object *obj, int
+extern const char CPL_DLL* json_object_to_json_string_ext(struct json_object *obj, int
 flags);
 
 /**
@@ -213,7 +214,7 @@ flags);
  *
  * @returns a json_object of type json_type_object
  */
-extern struct json_object* json_object_new_object(void);
+extern struct json_object CPL_DLL* json_object_new_object(void);
 
 /** Get the hashtable of a json_object of type json_type_object
  * @param obj the json_object instance
@@ -242,7 +243,7 @@ extern int json_object_object_length(struct json_object* obj);
  * @param key the object field name (a private copy will be duplicated)
  * @param val a json_object or NULL member to associate with the given field
  */
-extern void json_object_object_add(struct json_object* obj, const char *key,
+extern void CPL_DLL json_object_object_add(struct json_object* obj, const char *key,
 				   struct json_object *val);
 
 /** Get the json_object associate with a given object field
@@ -352,7 +353,7 @@ extern void json_object_object_del(struct json_object* obj, const char *key);
 /** Create a new empty json_object of type json_type_array
  * @returns a json_object of type json_type_array
  */
-extern struct json_object* json_object_new_array(void);
+extern struct json_object CPL_DLL * json_object_new_array(void);
 
 /** Get the arraylist of a json_object of type json_type_array
  * @param obj the json_object instance
@@ -385,7 +386,7 @@ extern void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const
  * @param obj the json_object instance
  * @param val the json_object to be added
  */
-extern int json_object_array_add(struct json_object *obj,
+extern int CPL_DLL json_object_array_add(struct json_object *obj,
 				 struct json_object *val);
 
 /** Insert or replace an element at a specified index in an array (a json_object of type json_type_array)
@@ -444,14 +445,14 @@ extern json_bool json_object_get_boolean(struct json_object *obj);
  * @param i the integer
  * @returns a json_object of type json_type_int
  */
-extern struct json_object* json_object_new_int(int32_t i);
+extern struct json_object CPL_DLL* json_object_new_int(int32_t i);
 
 
 /** Create a new empty json_object of type json_type_int
  * @param i the integer
  * @returns a json_object of type json_type_int
  */
-extern struct json_object* json_object_new_int64(int64_t i);
+extern struct json_object CPL_DLL* json_object_new_int64(int64_t i);
 
 
 /** Get the int value of a json_object
@@ -492,7 +493,7 @@ extern int64_t json_object_get_int64(struct json_object *obj);
  * @param d the double
  * @returns a json_object of type json_type_double
  */
-extern struct json_object* json_object_new_double(double d);
+extern struct json_object CPL_DLL* json_object_new_double(double d);
 
 /** Get the double floating point value of a json_object
  *
@@ -529,7 +530,7 @@ extern double json_object_get_double(struct json_object *obj);
  * @param s the string
  * @returns a json_object of type json_type_string
  */
-extern struct json_object* json_object_new_string(const char *s);
+extern struct json_object CPL_DLL* json_object_new_string(const char *s);
 
 extern struct json_object* json_object_new_string_len(const char *s, int len);
 
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
index 0bc4047..1e9fcd5 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonreader.cpp 28898 2015-04-13 22:25:53Z rouault $
+ * $Id: ogrgeojsonreader.cpp 29156 2015-05-05 10:19:17Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONReader class (OGR GeoJSON Driver).
@@ -1069,11 +1069,12 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Invalid Feature object. "
-                  "Missing \'geometry\' member." );
-        delete poFeature;
-        return NULL;
+        static int bWarned = FALSE;
+        if( !bWarned )
+        {
+            bWarned = TRUE;
+            CPLDebug("GeoJSON", "Non conformant Feature object. Missing \'geometry\' member." );
+        }
     }
 
     return poFeature;
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
index 090d611..93ae2bc 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonwriter.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ogrgeojsonwriter.h 29243 2015-05-24 15:53:26Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines GeoJSON reader within OGR OGRGeoJSON Driver.
@@ -36,7 +36,7 @@
 /************************************************************************/
 /*                         FORWARD DECLARATIONS                         */
 /************************************************************************/
-
+#ifdef __cplusplus
 class OGRFeature;
 class OGRGeometry;
 class OGRPoint;
@@ -47,13 +47,16 @@ class OGRLinearRing;
 class OGRPolygon;
 class OGRMultiPolygon;
 class OGRGeometryCollection;
+#endif
 
-json_object* json_object_new_double_with_precision(double dfVal, int nCoordPrecision);
+CPL_C_START
+json_object CPL_DLL *json_object_new_double_with_precision(double dfVal, int nCoordPrecision);
+CPL_C_END
 
 /************************************************************************/
 /*                 GeoJSON Geometry Translators                         */
 /************************************************************************/
-
+#ifdef __cplusplus
 json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX, int nCoordPrecision );
 json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature );
 json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry, int nCoordPrecision );
@@ -68,5 +71,6 @@ json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometr
 json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, int nCoordPrecision );
 json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double const& fZ, int nCoordPrecision );
 json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine, int nCoordPrecision );
+#endif
 
 #endif /* OGR_GEOJSONWRITER_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gml/drv_gml.html b/ogr/ogrsf_frmts/gml/drv_gml.html
index ccfe571..514d0f7 100644
--- a/ogr/ogrsf_frmts/gml/drv_gml.html
+++ b/ogr/ogrsf_frmts/gml/drv_gml.html
@@ -325,7 +325,7 @@ the layers must be read in the order they appear in the file.<p>
 If no .xsd and .gfs files are found, the parser will detect the layout of layers when
 building the .gfs file. If the layers are found to be sequential, a <i><SequentialLayers>true</SequentialLayers></i>
 element will be written in the .gfs file, so that the GML_READ_MODE will be automatically
-initialized to MONOBLOCK_LAYERS if not explicitly set by the user.<p>
+initialized to SEQUENTIAL_LAYERS if not explicitly set by the user.<p>
 
 Starting with OGR 1.9.0, the GML_READ_MODE configuration option can be set to INTERLEAVED_LAYERS to be able
 to read a GML file whose features from different layers are interleaved. In the case, the semantics of the
@@ -357,11 +357,35 @@ belongs to another layer. In that case, the file should be read with code simila
 
 <ul>
 <li> <b>XSD=filename</b>: (GDAL >=2.0) to specify an explicit filename for the XSD
-application schema to use</li>.
+application schema to use.</li>
 <li> <b>FORCE_SRS_DETECTION=YES/NO</b>: (GDAL >=2.0) Force a full scan to detect the SRS of layers.
 This option may be needed in the case where the .gml file is accompanied with
 a .xsd. Normally in that situation, OGR would not detect the SRS, because this
 requires to do a full scan of the file. Defaults to NO</li>
+<li> <b>EMPTY_AS_NULL=YES/NO</b>: (GDAL >=2.0) By default (EMPTY_AS_NULL=YES),
+fields with empty content will be reported as being NULL, instead of being an empty
+string. This is the historic behaviour. However this will prevent such fields to
+be declared as not-nullable if the application schema declared them as mandatory.
+So this option can be set to NO to have both empty strings being report as such,
+and mandatory fields being reported as not nullable.</li>
+<li> <b>GML_ATTRIBUTES_TO_OGR_FIELDS=YES/NO</b>: (GDAL >=2.0) Whether GM
+Lattributes should be reported as OGR fields. Note that this option has only an
+effect the first time a GML file is opened (before the .gfs file is created),
+and if it has no valid associated .xsd. Defaults to NO.</li>
+<li> <b>INVERT_AXIS_ORDER_IF_LAT_LONG=YES/NO</b>: (GDAL >=2.0) Whether to
+present SRS and coordinate ordering in traditional GIS order. Defaults to YES.</li>
+<li> <b>CONSIDER_EPSG_AS_URN=YES/NO/AUTO</b>: (GDAL >=2.0) Whether to
+consider srsName like EPSG:XXXX as respecting EPSG axis order. Defaults to AUTO.</li>
+<li> <b>READ_MODE=AUTO/STANDARD/SEQUENTIAL_LAYERS/INTERLEAVED_LAYERS</b>: (GDAL >=2.0)
+Read mode. Defaults to AUTO.</li>
+<li> <b>EXPOSE_GML_ID=YES/NO/AUTO</b>: (GDAL >=2.0)
+Whether to make feature gml:id as a gml_id attribute. Defaults to AUTO.</li>
+<li> <b>EXPOSE_FID=YES/NO/AUTO</b>: (GDAL >=2.0)
+Whether to make feature fid as a fid attribute. Defaults to AUTO.</li>
+<li> <b>DOWNLOAD_SCHEMA=YES/NO</b>: (GDAL >=2.0)
+Whether to download the remote application schema if needed (only for WFS currently). Defaults to YES.</li>
+<li> <b>REGISTRY=filename</b>: (GDAL >=2.0)
+Filename of the registry with application schemas. Defaults to {GDAL_DATA}/gml_registry.xml.</li>
 </ul>
 
 <h2>Creation Issues</h2>
diff --git a/ogr/ogrsf_frmts/gml/gmlhandler.cpp b/ogr/ogrsf_frmts/gml/gmlhandler.cpp
index b2fc102..82a0079 100644
--- a/ogr/ogrsf_frmts/gml/gmlhandler.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlhandler.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlhandler.cpp 29026 2015-04-26 14:45:00Z rouault $
+ * $Id: gmlhandler.cpp 29217 2015-05-21 09:08:48Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLHandler class.
@@ -791,25 +791,22 @@ void GMLHandler::DealWithAttributes(const char *pszName, int nLenName, void* att
         /* Hard-coded historic cases */
         else if( strcmp(pszAttrKey, "xlink:href") == 0 )
         {
-            if (m_bReportHref)
+            if( (m_bReportHref || m_poReader->ReportAllAttributes()) && m_bInCurField )
             {
-                if( m_bInCurField )
-                {
-                    CPLFree(m_pszHref);
-                    m_pszHref = pszAttrVal;
-                    pszAttrVal = NULL;
-                }
-                else if( !poClass->IsSchemaLocked() ||
-                         (nAttrIndex =
-                            m_poReader->GetAttributeElementIndex( CPLSPrintf("%s_href", pszName ),
-                                                      nLenName + 5 )) != -1 )
-                {
-                    poState->PushPath( pszName, nLenName );
-                    CPLString osPropNameHref = poState->osPath + "_href";
-                    poState->PopPath();
-                    m_poReader->SetFeaturePropertyDirectly( osPropNameHref, pszAttrVal, nAttrIndex );
-                    pszAttrVal = NULL;
-                }
+                CPLFree(m_pszHref);
+                m_pszHref = pszAttrVal;
+                pszAttrVal = NULL;
+            }
+            else if( (!poClass->IsSchemaLocked() && (m_bReportHref || m_poReader->ReportAllAttributes())) ||
+                        (poClass->IsSchemaLocked() && (nAttrIndex =
+                        m_poReader->GetAttributeElementIndex( CPLSPrintf("%s_href", pszName ),
+                                                    nLenName + 5 )) != -1) )
+            {
+                poState->PushPath( pszName, nLenName );
+                CPLString osPropNameHref = poState->osPath + "_href";
+                poState->PopPath();
+                m_poReader->SetFeaturePropertyDirectly( osPropNameHref, pszAttrVal, nAttrIndex );
+                pszAttrVal = NULL;
             }
         }
         else if( strcmp(pszAttrKey, "uom") == 0 )
@@ -1593,7 +1590,7 @@ OGRErr GMLHandler::endElementAttribute()
 
     if (m_bInCurField)
     {
-        if (m_pszCurField == NULL)
+        if (m_pszCurField == NULL && m_poReader->IsEmptyAsNull())
         {
             if (m_pszValue != NULL)
             {
@@ -1605,7 +1602,7 @@ OGRErr GMLHandler::endElementAttribute()
         else
         {
             m_poReader->SetFeaturePropertyDirectly( poState->osPath.c_str(),
-                                            m_pszCurField,
+                                            m_pszCurField ? m_pszCurField : CPLStrdup(""),
                                             m_nAttributeIndex );
             m_pszCurField = NULL;
         }
diff --git a/ogr/ogrsf_frmts/gml/gmlreader.cpp b/ogr/ogrsf_frmts/gml/gmlreader.cpp
index ece3448..e2ef1b3 100644
--- a/ogr/ogrsf_frmts/gml/gmlreader.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreader.cpp 29094 2015-05-01 18:55:27Z rouault $
+ * $Id: gmlreader.cpp 29217 2015-05-21 09:08:48Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReader class.
@@ -184,10 +184,10 @@ CPL_UNUSED
 
     m_bSetWidthFlag = TRUE;
 
-    m_bReportAllAttributes = CSLTestBoolean(
-                    CPLGetConfigOption("GML_ATTRIBUTES_TO_OGR_FIELDS", "NO"));
+    m_bReportAllAttributes = FALSE;
 
     m_bIsWFSJointLayer = FALSE;
+    m_bEmptyAsNull = TRUE;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/gml/gmlreaderp.h b/ogr/ogrsf_frmts/gml/gmlreaderp.h
index 84b2ff2..202b573 100644
--- a/ogr/ogrsf_frmts/gml/gmlreaderp.h
+++ b/ogr/ogrsf_frmts/gml/gmlreaderp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreaderp.h 29051 2015-04-29 17:18:37Z rouault $
+ * $Id: gmlreaderp.h 29217 2015-05-21 09:08:48Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Private Declarations for OGR free GML Reader code.
@@ -465,6 +465,8 @@ private:
     int           m_bReportAllAttributes;
     
     int           m_bIsWFSJointLayer;
+    
+    int           m_bEmptyAsNull;
 
     int           ParseXMLHugeFile( const char *pszOutputFilename, 
                                     const int bSqliteIsTempFile,
@@ -550,10 +552,14 @@ public:
 
     int         IsSequentialLayers() const { return m_bSequentialLayers == TRUE; }
     
+    void        SetReportAllAttributes(int bFlag) { m_bReportAllAttributes = bFlag; }
     int         ReportAllAttributes() const { return m_bReportAllAttributes; }
     
     void             SetIsWFSJointLayer( int bFlag ) { m_bIsWFSJointLayer = bFlag; }
     int              IsWFSJointLayer() const { return m_bIsWFSJointLayer; }
+    
+    void             SetEmptyAsNull( int bFlag ) { m_bEmptyAsNull = bFlag; }
+    int              IsEmptyAsNull() const { return m_bEmptyAsNull; }
 
     static CPLMutex* hMutex;
 };
diff --git a/ogr/ogrsf_frmts/gml/gmlregistry.cpp b/ogr/ogrsf_frmts/gml/gmlregistry.cpp
index 12290ec..ca20a26 100644
--- a/ogr/ogrsf_frmts/gml/gmlregistry.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlregistry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlregistry.cpp 27150 2014-04-09 19:59:33Z martinl $
+ * $Id: gmlregistry.cpp 29240 2015-05-24 10:58:38Z rouault $
  *
  * Project:  GML registry
  * Purpose:  GML reader
@@ -35,15 +35,15 @@
 
 int GMLRegistry::Parse()
 {
-    const char* pszFilename;
-    pszFilename = CPLGetConfigOption("GML_REGISTRY", NULL);
-    if( pszFilename == NULL )
+    if( osRegistryPath.size() == 0 )
     {
-        pszFilename = CPLFindFile( "gdal", "gml_registry.xml" );
+        const char* pszFilename = CPLFindFile( "gdal", "gml_registry.xml" );
+        if( pszFilename )
+            osRegistryPath = pszFilename;
     }
-    if( pszFilename == NULL )
+    if( osRegistryPath.size() == 0 )
         return FALSE;
-    CPLXMLNode* psRootNode = CPLParseXMLFile(pszFilename);
+    CPLXMLNode* psRootNode = CPLParseXMLFile(osRegistryPath);
     if( psRootNode == NULL )
         return FALSE;
     CPLXMLNode *psRegistryNode = CPLGetXMLNode( psRootNode, "=gml_registry" );
@@ -59,7 +59,7 @@ int GMLRegistry::Parse()
             strcmp(psIter->pszValue, "namespace") == 0 )
         {
             GMLRegistryNamespace oNameSpace;
-            if( oNameSpace.Parse(pszFilename, psIter) )
+            if( oNameSpace.Parse(osRegistryPath, psIter) )
             {
                 aoNamespaces.push_back(oNameSpace);
             }
diff --git a/ogr/ogrsf_frmts/gml/gmlregistry.h b/ogr/ogrsf_frmts/gml/gmlregistry.h
index eaed077..837512c 100644
--- a/ogr/ogrsf_frmts/gml/gmlregistry.h
+++ b/ogr/ogrsf_frmts/gml/gmlregistry.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlregistry.h 27150 2014-04-09 19:59:33Z martinl $
+ * $Id: gmlregistry.h 29240 2015-05-24 10:58:38Z rouault $
  *
  * Project:  GML registry
  * Purpose:  GML reader
@@ -61,9 +61,12 @@ class GMLRegistryNamespace
 
 class GMLRegistry
 {
+        CPLString osRegistryPath;
+
     public:
         std::vector<GMLRegistryNamespace> aoNamespaces;
 
+        GMLRegistry(const CPLString& osRegistryPath) : osRegistryPath(osRegistryPath) {}
         int Parse();
 };
 
diff --git a/ogr/ogrsf_frmts/gml/ogr_gml.h b/ogr/ogrsf_frmts/gml/ogr_gml.h
index c7deab3..5adc217 100644
--- a/ogr/ogrsf_frmts/gml/ogr_gml.h
+++ b/ogr/ogrsf_frmts/gml/ogr_gml.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gml.h 29013 2015-04-25 18:12:21Z rouault $
+ * $Id: ogr_gml.h 29214 2015-05-20 13:47:29Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Declarations for OGR wrapper classes for GML, and GML<->OGR
@@ -150,6 +150,8 @@ class OGRGMLDataSource : public OGRDataSource
     ReadMode            eReadMode;
     GMLFeature         *poStoredGMLFeature;
     OGRGMLLayer        *poLastReadLayer;
+    
+    int                 bEmptyAsNull;
 
     void                FindAndParseTopElements(VSILFILE* fp);
     void                SetExtents(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
diff --git a/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp b/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
index 5b84750..3a6ebe0 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgmldatasource.cpp 29091 2015-05-01 18:20:25Z rouault $
+ * $Id: ogrgmldatasource.cpp 29240 2015-05-24 10:58:38Z rouault $
  *
  * Project:  OGR
  * Purpose:  Implements OGRGMLDataSource class.
@@ -47,7 +47,7 @@
 
 #include <vector>
 
-CPL_CVSID("$Id: ogrgmldatasource.cpp 29091 2015-05-01 18:20:25Z rouault $");
+CPL_CVSID("$Id: ogrgmldatasource.cpp 29240 2015-05-24 10:58:38Z rouault $");
 
 static int ExtractSRSName(const char* pszXML, char* szSRSName,
                           size_t sizeof_szSRSName);
@@ -117,6 +117,7 @@ OGRGMLDataSource::OGRGMLDataSource()
     m_bInvertAxisOrderIfLatLong = FALSE;
     m_bConsiderEPSGAsURN = FALSE;
     m_bGetSecondaryGeometryOption = FALSE;
+    bEmptyAsNull = TRUE;
 }
 
 /************************************************************************/
@@ -488,11 +489,13 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         bExposeFid = strstr(szPtr, " fid=\"") != NULL ||
                         strstr(szPtr, " fid='") != NULL;
         
-        const char* pszExposeGMLId = CPLGetConfigOption("GML_EXPOSE_GML_ID", NULL);
+        const char* pszExposeGMLId = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+            "EXPOSE_GML_ID", CPLGetConfigOption("GML_EXPOSE_GML_ID", NULL));
         if (pszExposeGMLId)
             bExposeGMLId = CSLTestBoolean(pszExposeGMLId);
 
-        const char* pszExposeFid = CPLGetConfigOption("GML_EXPOSE_FID", NULL);
+        const char* pszExposeFid = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+            "EXPOSE_FID", CPLGetConfigOption("GML_EXPOSE_FID", NULL));
         if (pszExposeFid)
             bExposeFid = CSLTestBoolean(pszExposeFid);
     }
@@ -528,7 +531,11 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
 /*      We assume now that it is GML.  Instantiate a GMLReader on it.   */
 /* -------------------------------------------------------------------- */
 
-    const char* pszReadMode = CPLGetConfigOption("GML_READ_MODE", NULL);
+    const char* pszReadMode = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+            "READ_MODE",
+            CPLGetConfigOption("GML_READ_MODE", "AUTO"));
+    if( EQUAL(pszReadMode, "AUTO") )
+        pszReadMode = NULL;
     if (pszReadMode == NULL || EQUAL(pszReadMode, "STANDARD"))
         eReadMode = STANDARD;
     else if (EQUAL(pszReadMode, "SEQUENTIAL_LAYERS"))
@@ -540,12 +547,16 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         CPLDebug("GML", "Unrecognized value for GML_READ_MODE configuration option.");
     }
 
-    m_bInvertAxisOrderIfLatLong = CSLTestBoolean(
-        CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", "YES"));
+    m_bInvertAxisOrderIfLatLong = 
+        CSLTestBoolean(CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+            "INVERT_AXIS_ORDER_IF_LAT_LONG",
+            CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", "YES")));
 
     const char* pszConsiderEPSGAsURN =
-        CPLGetConfigOption("GML_CONSIDER_EPSG_AS_URN", NULL);
-    if (pszConsiderEPSGAsURN != NULL)
+        CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+            "CONSIDER_EPSG_AS_URN",
+            CPLGetConfigOption("GML_CONSIDER_EPSG_AS_URN", "AUTO"));
+    if( !EQUAL(pszConsiderEPSGAsURN, "AUTO") )
         m_bConsiderEPSGAsURN = CSLTestBoolean(pszConsiderEPSGAsURN);
     else if (bHintConsiderEPSGAsURN)
     {
@@ -590,6 +601,11 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
 
     poReader->SetSourceFile( pszFilename );
     ((GMLReader*)poReader)->SetIsWFSJointLayer(bIsWFSJointLayer);
+    bEmptyAsNull = CSLFetchBoolean(poOpenInfo->papszOpenOptions, "EMPTY_AS_NULL", TRUE);
+    ((GMLReader*)poReader)->SetEmptyAsNull(bEmptyAsNull);
+    ((GMLReader*)poReader)->SetReportAllAttributes(
+        CSLFetchBoolean(poOpenInfo->papszOpenOptions, "GML_ATTRIBUTES_TO_OGR_FIELDS",
+            CSLTestBoolean(CPLGetConfigOption("GML_ATTRIBUTES_TO_OGR_FIELDS", "NO"))));
 
 /* -------------------------------------------------------------------- */
 /*      Find <gml:description>, <gml:name> and <gml:boundedBy>          */
@@ -666,7 +682,8 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
 /*      Is some GML Feature Schema (.gfs) TEMPLATE required ?           */
 /* -------------------------------------------------------------------- */
     const char *pszGFSTemplateName = 
-                CPLGetConfigOption( "GML_GFS_TEMPLATE", NULL);
+        CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "GFS_TEMPLATE",
+                CPLGetConfigOption( "GML_GFS_TEMPLATE", NULL));
     if( pszGFSTemplateName != NULL )
     {
         /* attempting to load the GFS TEMPLATE */
@@ -798,7 +815,9 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         /* that might match a declared namespace and featuretype */
         if( !bHasFoundXSD )
         {
-            GMLRegistry oRegistry;
+            GMLRegistry oRegistry(CSLFetchNameValueDef(
+                    poOpenInfo->papszOpenOptions, "REGISTRY",
+                                    CPLGetConfigOption("GML_REGISTRY", "")));
             if( oRegistry.Parse() )
             {
                 CPLString osHeader(szHeader);
@@ -918,7 +937,9 @@ int OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
                             papszTypeNames = CSLTokenizeString2( osTypeName, ",", 0);
 
                             if (!bHasFoundXSD && CPLHTTPEnabled() &&
-                                CSLTestBoolean(CPLGetConfigOption("GML_DOWNLOAD_WFS_SCHEMA", "YES")))
+                                CSLFetchBoolean(poOpenInfo->papszOpenOptions,
+                                    "DOWNLOAD_SCHEMA",
+                                    CSLTestBoolean(CPLGetConfigOption("GML_DOWNLOAD_WFS_SCHEMA", "YES"))) )
                             {
                                 CPLHTTPResult* psResult = CPLHTTPFetch(pszEscapedURL, NULL);
                                 if (psResult)
@@ -1496,7 +1517,8 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
             oField.SetSubType(OFSTInt16);
         else if( poProperty->GetType() == GMLPT_Float) 
             oField.SetSubType(OFSTFloat32);
-        oField.SetNullable(poProperty->IsNullable() );
+        if( !bEmptyAsNull )
+            oField.SetNullable(poProperty->IsNullable() );
 
         poLayer->GetLayerDefn()->AddFieldDefn( &oField );
     }
diff --git a/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp b/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
index 34880ae..f8e4a8d 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgmldriver.cpp 29051 2015-04-29 17:18:37Z rouault $
+ * $Id: ogrgmldriver.cpp 29240 2015-05-24 10:58:38Z rouault $
  *
  * Project:  OGR
  * Purpose:  OGRGMLDriver implementation
@@ -32,7 +32,7 @@
 #include "cpl_multiproc.h"
 #include "gmlreaderp.h"
 
-CPL_CVSID("$Id: ogrgmldriver.cpp 29051 2015-04-29 17:18:37Z rouault $");
+CPL_CVSID("$Id: ogrgmldriver.cpp 29240 2015-05-24 10:58:38Z rouault $");
 
 /************************************************************************/
 /*                        OGRGMLDriverUnload()                          */
@@ -163,7 +163,34 @@ void RegisterOGRGML()
         poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
 "  <Option name='XSD' type='string' description='Name of the related application schema file (.xsd).'/>"
+"  <Option name='GFS_TEMPLATE' type='string' description='Filename of a .gfs template file to appli.'/>"
 "  <Option name='FORCE_SRS_DETECTION' type='boolean' description='Force a full scan to detect the SRS of layers.' default='NO'/>"
+"  <Option name='EMPTY_AS_NULL' type='boolean' description='Force empty fields to be reported as NULL. Set to NO so that not-nullable fields can be exposed' default='YES'/>"
+"  <Option name='GML_ATTRIBUTES_TO_OGR_FIELDS' type='boolean' description='Whether GML attributes should be reported as OGR fields' default='NO'/>"
+"  <Option name='INVERT_AXIS_ORDER_IF_LAT_LONG' type='boolean' description='Whether to present SRS and coordinate ordering in traditional GIS order' default='YES'/>"
+"  <Option name='CONSIDER_EPSG_AS_URN' type='string-select' description='Whether to consider srsName like EPSG:XXXX as respecting EPSG axis order' default='AUTO'>"
+"    <Value>AUTO</Value>"
+"    <Value>YES</Value>"
+"    <Value>NO</Value>"
+"  </Option>"
+"  <Option name='READ_MODE' type='string-select' description='Read mode' default='AUTO'>"
+"    <Value>AUTO</Value>"
+"    <Value>STANDARD</Value>"
+"    <Value>SEQUENTIAL_LAYERS</Value>"
+"    <Value>INTERLEAVED_LAYERS</Value>"
+"  </Option>"
+"  <Option name='EXPOSE_GML_ID' type='string-select' description='Whether to make feature gml:id as a gml_id attribute' default='AUTO'>"
+"    <Value>AUTO</Value>"
+"    <Value>YES</Value>"
+"    <Value>NO</Value>"
+"  </Option>"
+"  <Option name='EXPOSE_FID' type='string-select' description='Whether to make feature fid as a fid attribute' default='AUTO'>"
+"    <Value>AUTO</Value>"
+"    <Value>YES</Value>"
+"    <Value>NO</Value>"
+"  </Option>"
+"  <Option name='DOWNLOAD_SCHEMA' type='boolean' description='Whether to download the remote application schema if needed (only for WFS currently)' default='YES'/>"
+"  <Option name='REGISTRY' type='string' description='Filename of the registry with application schemas.'/>"
 "</OpenOptionList>" );
 
         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
diff --git a/ogr/ogrsf_frmts/gpkg/drv_geopackage.html b/ogr/ogrsf_frmts/gpkg/drv_geopackage.html
index 7f85d8b..a888b46 100644
--- a/ogr/ogrsf_frmts/gpkg/drv_geopackage.html
+++ b/ogr/ogrsf_frmts/gpkg/drv_geopackage.html
@@ -72,14 +72,20 @@ The following functions, with identical syntax and semantics as in Spatialite, a
 
 <h3>Link with Spatialite</h3>
 
-Starting with GDAL 2.0, if it has been compiled against Spatialite 4.2 or later, it is also possible
-to use Spatialite SQL functions. Explicit transformation from GPKG geometry binary
-encoding to/from Spatialite geometry binary encoding must be done.
+<p>
+Starting with GDAL 2.0, if it has been compiled against Spatialite 4.2 or later,
+it is also possible to use Spatialite SQL functions. Explicit transformation
+from GPKG geometry binary encoding to Spatialite geometry binary encoding must be done.
+</p>
 
 <pre>
-ogrinfo poly.gpkg -sql "SELECT AsGPB(ST_Buffer(CastAutomagic(geom),5)) FROM poly"
+ogrinfo poly.gpkg -sql "SELECT ST_Buffer(CastAutomagic(geom),5) FROM poly"
 </pre>
 
+<p>
+Starting with Spatialite 4.3, CastAutomagic is no longer needed.
+</p>
+
 <h2>Transaction support (GDAL >= 2.0)</h2>
 
 <p>
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
index 391b4fb..838da51 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
@@ -4258,6 +4258,11 @@ int GDALGeoPackageDataset::OpenOrCreateDB(int flags)
 
 #ifdef SPATIALITE_412_OR_LATER
     InitNewSpatialite();
+
+    // Enable Spatialite 4.3 "amphibious" mode, i.e. that spatialite functions
+    // that take geometries will accept GPKG encoded gometries without
+    // explicit conversion
+    sqlite3_exec(hDB, "SELECT EnableGpkgAmphibiousMode()", NULL, NULL, NULL);
 #endif
 
     /* Used by RTree Spatial Index Extension */
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp
index 0e13c57..743ad2e 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp
@@ -346,6 +346,12 @@ void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName,
         if( EQUAL(oField.GetNameRef(),"_rowid_") )
             continue;
 
+        // this will avoid the old geom field to appear when running something
+        // like "select st_buffer(geom,5) as geom, * from my_layer"
+        if( m_poFeatureDefn->GetGeomFieldCount() &&
+            EQUAL(oField.GetNameRef(), m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef()) )
+            continue;
+
         int nColType = sqlite3_column_type( hStmt, iCol );
         const char * pszDeclType = sqlite3_column_decltype(hStmt, iCol);
 
diff --git a/ogr/ogrsf_frmts/gpsbabel/drv_gpsbabel.html b/ogr/ogrsf_frmts/gpsbabel/drv_gpsbabel.html
index e39bf31..f70421d 100644
--- a/ogr/ogrsf_frmts/gpsbabel/drv_gpsbabel.html
+++ b/ogr/ogrsf_frmts/gpsbabel/drv_gpsbabel.html
@@ -42,6 +42,7 @@ includes for now :
 <li>nmea</li>
 <li>osm</li>
 <li>ozi</li>
+<li>igc</li>
 </ul>
 <p>
 
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h b/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h
index 570797f..1db5306 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h
+++ b/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gpsbabel.h 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogr_gpsbabel.h 29172 2015-05-07 22:15:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/GPSBabel driver.
@@ -60,7 +60,8 @@ class OGRGPSBabelDataSource : public OGRDataSource
     virtual int         TestCapability( const char * );
 
     int                 Open ( const char* pszFilename,
-                               const char* pszGPSBabelDriverNameIn );
+                               const char* pszGPSBabelDriverNameIn,
+                               char** papszOpenOptions );
 
     static int          IsSpecialFile(const char* pszFilename);
     static int          IsValidDriverName(const char* pszGPSBabelDriverName);
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
index c57a374..7719727 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
+++ b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgpsbabeldatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
+ * $Id: ogrgpsbabeldatasource.cpp 29177 2015-05-09 19:29:02Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGPSBabelDataSource class.
@@ -35,7 +35,7 @@
 
 #include <string.h>
 
-CPL_CVSID("$Id: ogrgpsbabeldatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrgpsbabeldatasource.cpp 29177 2015-05-09 19:29:02Z rouault $");
 
 /************************************************************************/
 /*                      OGRGPSBabelDataSource()                         */
@@ -149,7 +149,8 @@ int OGRGPSBabelDataSource::IsValidDriverName(const char* pszGPSBabelDriverName)
 /************************************************************************/
 
 int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
-                                 const char* pszGPSBabelDriverNameIn )
+                                 const char* pszGPSBabelDriverNameIn,
+                                 char** papszOpenOptions )
 
 {
     int bExplicitFeatures = FALSE;
@@ -161,6 +162,28 @@ int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
         pszGPSBabelDriverName = CPLStrdup(pszGPSBabelDriverNameIn);
         pszFilename = CPLStrdup(pszDatasourceName);
     }
+    else
+    {
+        if( CSLFetchNameValue(papszOpenOptions, "FILENAME") )
+            pszFilename = CPLStrdup(CSLFetchNameValue(papszOpenOptions,
+                                                      "FILENAME"));
+
+        if( CSLFetchNameValue(papszOpenOptions, "GPSBABEL_DRIVER") )
+        {
+            if( pszFilename == NULL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Missing FILENAME");
+                return FALSE;
+            }
+
+            pszGPSBabelDriverName = CPLStrdup(CSLFetchNameValue(papszOpenOptions,
+                                                            "DRIVER"));
+
+            /* A bit of validation to avoid command line injection */
+            if (!IsValidDriverName(pszGPSBabelDriverName))
+                return FALSE;
+        }
+    }
 
     pszName = CPLStrdup( pszDatasourceName );
 
@@ -223,7 +246,8 @@ int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
             pszSep = pszNextSep;
         }
 
-        pszFilename = CPLStrdup(pszSep+1);
+        if( pszFilename == NULL )
+            pszFilename = CPLStrdup(pszSep+1);
     }
 
     const char* pszOptionUseTempFile = CPLGetConfigOption("USE_TEMPFILE", NULL);
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp
index cce0a00..8f6678c 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp
+++ b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp
@@ -29,58 +29,103 @@
 
 #include "ogr_gpsbabel.h"
 #include "cpl_conv.h"
+#include "cpl_spawn.h"
 
 // g++ -g -Wall -fPIC  ogr/ogrsf_frmts/gpsbabel/*.cpp -shared -o ogr_GPSBabel.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/gpsbabel -L. -lgdal
 
 CPL_CVSID("$Id$");
 
 /************************************************************************/
+/*                         OGRGPSBabelDriverIdentify()                  */
+/************************************************************************/
+
+static int OGRGPSBabelDriverIdentifyInternal( GDALOpenInfo* poOpenInfo,
+                                              const char** ppszGSPBabelDriverName )
+{
+    if( EQUALN(poOpenInfo->pszFilename, "GPSBABEL:", strlen("GPSBABEL:")) )
+        return TRUE;
+
+    const char* pszGPSBabelDriverName = NULL;
+    if( poOpenInfo->fpL == NULL )
+            return FALSE;
+
+    if (memcmp(poOpenInfo->pabyHeader, "MsRcd", 5) == 0)
+        pszGPSBabelDriverName = "mapsource";
+    else if (memcmp(poOpenInfo->pabyHeader, "MsRcf", 5) == 0)
+        pszGPSBabelDriverName = "gdb";
+    else if (strstr((const char*)poOpenInfo->pabyHeader, "<osm") != NULL)
+        pszGPSBabelDriverName = "osm";
+    else if (strstr((const char*)poOpenInfo->pabyHeader, "$GPGSA") != NULL ||
+                strstr((const char*)poOpenInfo->pabyHeader, "$GPGGA") != NULL)
+        pszGPSBabelDriverName = "nmea";
+    else if (EQUALN((const char*)poOpenInfo->pabyHeader, "OziExplorer",11))
+        pszGPSBabelDriverName = "ozi";
+    else if (strstr((const char*)poOpenInfo->pabyHeader, "Grid") &&
+                strstr((const char*)poOpenInfo->pabyHeader, "Datum") &&
+                strstr((const char*)poOpenInfo->pabyHeader, "Header"))
+        pszGPSBabelDriverName = "garmin_txt";
+    else if (poOpenInfo->pabyHeader[0] == 13 && poOpenInfo->pabyHeader[10] == 'M' && poOpenInfo->pabyHeader[11] == 'S' &&
+                (poOpenInfo->pabyHeader[12] >= '0' && poOpenInfo->pabyHeader[12] <= '9') &&
+                (poOpenInfo->pabyHeader[13] >= '0' && poOpenInfo->pabyHeader[13] <= '9') &&
+                poOpenInfo->pabyHeader[12] * 10 + poOpenInfo->pabyHeader[13] >= 30 &&
+                (poOpenInfo->pabyHeader[14] == 1 || poOpenInfo->pabyHeader[14] == 2) && poOpenInfo->pabyHeader[15] == 0 &&
+                poOpenInfo->pabyHeader[16] == 0 && poOpenInfo->pabyHeader[17] == 0)
+        pszGPSBabelDriverName = "mapsend";
+    else if (strstr((const char*)poOpenInfo->pabyHeader, "$PMGNWPL") != NULL ||
+                strstr((const char*)poOpenInfo->pabyHeader, "$PMGNRTE") != NULL)
+        pszGPSBabelDriverName = "magellan";
+    else if (poOpenInfo->pabyHeader[0] == 'A' &&
+                poOpenInfo->pabyHeader[1] >= 'A' && poOpenInfo->pabyHeader[1] <= 'Z' &&
+                poOpenInfo->pabyHeader[2] >= 'A' && poOpenInfo->pabyHeader[2] <= 'Z' &&
+                poOpenInfo->pabyHeader[3] >= 'A' && poOpenInfo->pabyHeader[3] <= 'Z' &&
+                EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "igc") )
+        pszGPSBabelDriverName = "igc";
+
+    static int bGPSBabelFound = -1;
+    if( pszGPSBabelDriverName != NULL && bGPSBabelFound < 0 )
+    {
+#ifndef WIN32
+        VSIStatBufL sStat;
+        bGPSBabelFound = VSIStatL("/usr/bin/gpsbabel", &sStat) == 0;
+        if( !bGPSBabelFound )
+#endif
+        {
+            const char* const apszArgs[] = { "gpsbabel", "-V", NULL };
+            CPLString osTmpFileName("/vsimem/gpsbabel_tmp.tmp");
+            VSILFILE* tmpfp = VSIFOpenL(osTmpFileName, "wb");
+            bGPSBabelFound = (CPLSpawn(apszArgs, NULL, tmpfp, FALSE) == 0);
+            VSIFCloseL(tmpfp);
+            VSIUnlink(osTmpFileName);
+        }
+    }
+
+    if( bGPSBabelFound )
+        *ppszGSPBabelDriverName = pszGPSBabelDriverName;
+    return ( *ppszGSPBabelDriverName != NULL );
+}
+
+static int OGRGPSBabelDriverIdentify( GDALOpenInfo* poOpenInfo )
+{
+    const char* pszGPSBabelDriverName = NULL;
+    return OGRGPSBabelDriverIdentifyInternal(poOpenInfo, &pszGPSBabelDriverName);
+}
+    
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
 static GDALDataset *OGRGPSBabelDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    if (poOpenInfo->eAccess == GA_Update)
-        return NULL;
     const char* pszGPSBabelDriverName = NULL;
-    if( !EQUALN(poOpenInfo->pszFilename, "GPSBABEL:", strlen("GPSBABEL:")) )
-    {
-        if( poOpenInfo->fpL == NULL )
-            return NULL;
-        if (memcmp(poOpenInfo->pabyHeader, "MsRcd", 5) == 0)
-            pszGPSBabelDriverName = "mapsource";
-        else if (memcmp(poOpenInfo->pabyHeader, "MsRcf", 5) == 0)
-            pszGPSBabelDriverName = "gdb";
-        else if (strstr((const char*)poOpenInfo->pabyHeader, "<osm") != NULL)
-            pszGPSBabelDriverName = "osm";
-        else if (strstr((const char*)poOpenInfo->pabyHeader, "$GPGSA") != NULL ||
-                 strstr((const char*)poOpenInfo->pabyHeader, "$GPGGA") != NULL)
-            pszGPSBabelDriverName = "nmea";
-        else if (EQUALN((const char*)poOpenInfo->pabyHeader, "OziExplorer",11))
-            pszGPSBabelDriverName = "ozi";
-        else if (strstr((const char*)poOpenInfo->pabyHeader, "Grid") &&
-                 strstr((const char*)poOpenInfo->pabyHeader, "Datum") &&
-                 strstr((const char*)poOpenInfo->pabyHeader, "Header"))
-            pszGPSBabelDriverName = "garmin_txt";
-        else if (poOpenInfo->pabyHeader[0] == 13 && poOpenInfo->pabyHeader[10] == 'M' && poOpenInfo->pabyHeader[11] == 'S' &&
-                 (poOpenInfo->pabyHeader[12] >= '0' && poOpenInfo->pabyHeader[12] <= '9') &&
-                 (poOpenInfo->pabyHeader[13] >= '0' && poOpenInfo->pabyHeader[13] <= '9') &&
-                 poOpenInfo->pabyHeader[12] * 10 + poOpenInfo->pabyHeader[13] >= 30 &&
-                 (poOpenInfo->pabyHeader[14] == 1 || poOpenInfo->pabyHeader[14] == 2) && poOpenInfo->pabyHeader[15] == 0 &&
-                 poOpenInfo->pabyHeader[16] == 0 && poOpenInfo->pabyHeader[17] == 0)
-            pszGPSBabelDriverName = "mapsend";
-        else if (strstr((const char*)poOpenInfo->pabyHeader, "$PMGNWPL") != NULL ||
-                 strstr((const char*)poOpenInfo->pabyHeader, "$PMGNRTE") != NULL)
-            pszGPSBabelDriverName = "magellan";
-
-        if( pszGPSBabelDriverName == NULL )
-            return NULL;
-    }
+    if (poOpenInfo->eAccess == GA_Update ||
+        !OGRGPSBabelDriverIdentifyInternal(poOpenInfo, &pszGPSBabelDriverName))
+        return NULL;
 
     OGRGPSBabelDataSource   *poDS = new OGRGPSBabelDataSource();
 
-    if( !poDS->Open( poOpenInfo->pszFilename, pszGPSBabelDriverName ) )
+    if( !poDS->Open( poOpenInfo->pszFilename, pszGPSBabelDriverName,
+                     poOpenInfo->papszOpenOptions ) )
     {
         delete poDS;
         poDS = NULL;
@@ -146,7 +191,21 @@ void RegisterOGRGPSBabel()
         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
                                    "drv_gpsbabel.html" );
 
+        poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "GPSBABEL:" );
+
+        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"<OpenOptionList>"
+"  <Option name='FILENAME' type='string' description='Filename to open'/>"
+"  <Option name='GPSBABEL_DRIVER' type='string' description='Name of the GPSBabel to use'/>"
+"</OpenOptionList>");
+
+        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+"<CreationOptionList>"
+"  <Option name='GPSBABEL_DRIVER' type='string' description='Name of the GPSBabel to use'/>"
+"</CreationOptionList>");
+
         poDriver->pfnOpen = OGRGPSBabelDriverOpen;
+        poDriver->pfnIdentify = OGRGPSBabelDriverIdentify;
         poDriver->pfnCreate = OGRGPSBabelDriverCreate;
         poDriver->pfnDelete = OGRGPSBabelDriverDelete;
 
diff --git a/ogr/ogrsf_frmts/ili/drv_ili.html b/ogr/ogrsf_frmts/ili/drv_ili.html
index 174aa42..c359e75 100644
--- a/ogr/ogrsf_frmts/ili/drv_ili.html
+++ b/ogr/ogrsf_frmts/ili/drv_ili.html
@@ -12,20 +12,21 @@ OGR has support for INTERLIS reading and writing.<br>
 
 With the usage of unified, documented geodata and the flexible exchange possibilities the following advantage may occur:
 <ul>
-<li>the standardized documentation 
-<li>the compatible data exchange 
-<li>the comprehensive integration of geodata e.g. from different data owners. 
-<li>the quality proofing 
-<li>the long term data storage 
-<li>the contract-proof security and the availability of the software 
+<li>the standardized documentation</li>
+<li>the compatible data exchange</li>
+<li>the comprehensive integration of geodata e.g. from different data owners.</li>
+<li>the quality proofing</li>
+<li>the long term data storage</li>
+<li>the contract-proof security and the availability of the software</li>
 </ul>
 
 OGR supports INTERLIS 1 and INTERLIS 2 (2.2 and 2.3) with the following limitations:
 <ul>
-<li>Curves are converted to line segments
-<li>Embedded INTERLIS 2 structures are not supported yet
-<li>Incremental transfer is not supported
-<li>Transfer id (TID) is used as feature id
+<li>Curves in Interlis 1 areas are converted to line segments</li>
+<li>Embedded INTERLIS 2 structures are not supported</li>
+<li>Incremental transfer is not supported</li>
+<li>Interlis 1 Surface geometries with non-numeric IDENT field are not included in the attribute layer</li>
+<li>Transfer id (TID) is used as feature id</li>
 </ul>
 
 <h2>Model support</h2>
@@ -78,10 +79,18 @@ ogr2ogr -f PostgreSQL PG:dbname=warmerda av_fixpunkte_mit_LFPNachfuehrung.itf,av
 <p>
 
 <h3>Arc interpolation</h3>
-INTERLIS arc geometries are converted to polygons.<br></br>
-The interpolation angle can be changed with the environment variable ARC_DEGREES (Default: 1 degree).<br></br>
+Converting INTERLIS arc geometries to line segements can be forced by setting the configuration
+variable OGR_STROKE_CURVE to TRUE.<br></br>
+The approximation of arcs as linestrings is done by splitting the arcs into subarcs of no more than a
+threshhold angle. This angle is the OGR_ARC_STEPSIZE. This defaults to
+one degree, but may be overridden by setting the configuration variable
+OGR_ARC_STEPSIZE.<br></br>
 
 
+<h3>OGR versions prior to 2.0</h3>
+
+Arcs are always interpolated and the interpolation angle can be configured with the environment variable ARC_DEGREES.<p>
+
 <h3>OGR versions prior to 1.11</h3>
 
 For using the INTERLIS model (.ili) a Java interpreter is needed at runtime and ili2c.jar (included in the 
diff --git a/ogr/ogrsf_frmts/ili/ogrili1layer.cpp b/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
index 5ec9419..370d316 100644
--- a/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrili1layer.cpp 29139 2015-05-03 20:09:20Z pka $
+ * $Id: ogrili1layer.cpp 29221 2015-05-21 13:40:23Z pka $
  *
  * Project:  Interlis 1 Translator
  * Purpose:  Implements OGRILI1Layer class.
@@ -33,7 +33,7 @@
 #include "cpl_string.h"
 #include "ogr_geos.h"
 
-CPL_CVSID("$Id: ogrili1layer.cpp 29139 2015-05-03 20:09:20Z pka $");
+CPL_CVSID("$Id: ogrili1layer.cpp 29221 2015-05-21 13:40:23Z pka $");
 
 /************************************************************************/
 /*                           OGRILI1Layer()                              */
@@ -422,6 +422,7 @@ OGRErr OGRILI1Layer::CreateField( OGRFieldDefn *poField, CPL_UNUSED int bApproxO
 
 void OGRILI1Layer::JoinGeomLayers()
 {
+    bGeomsJoined = TRUE;
     int bResetConfigOption = FALSE;
     if (EQUAL(CPLGetConfigOption("OGR_ARC_STEPSIZE", ""), ""))
     {
@@ -449,7 +450,6 @@ void OGRILI1Layer::JoinGeomLayers()
             }
         }
     }
-    bGeomsJoined = TRUE;
 
     if( bResetConfigOption )
         CPLSetThreadLocalConfigOption("OGR_ARC_STEPSIZE", NULL);
diff --git a/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html b/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
index ccdbc58..5d5fb65 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
+++ b/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
@@ -111,11 +111,11 @@ The corresponding entry should already be added to the spatial_ref_sys metadata
 
 <blockquote><pre>drop spatial index on schema.table</pre></blockquote>
 
-<h2>Transaction support (GDAL >= 2.0)</h2>
-
-<p>
-The driver implements transactions at the dataset level, per
-<a href="http://trac.osgeo.org/gdal/wiki/rfc54_dataset_transactions">RFC 54</a>
+<h2>Transaction support (GDAL >= 2.0)</h2>
+
+<p>
+The driver implements transactions at the dataset level, per
+<a href="http://trac.osgeo.org/gdal/wiki/rfc54_dataset_transactions">RFC 54</a>
 </p>
 
 <h2>Examples</h2>
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h b/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h
index 652daff..96e031c 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_mssqlspatial.h 29027 2015-04-26 18:29:41Z tamas $
+ * $Id: ogr_mssqlspatial.h 29185 2015-05-12 10:45:44Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
@@ -36,6 +36,12 @@
 
 class OGRMSSQLSpatialDataSource;
 
+/* layer status */
+#define MSSQLLAYERSTATUS_ORIGINAL  0
+#define MSSQLLAYERSTATUS_INITIAL 1
+#define MSSQLLAYERSTATUS_CREATED 2
+#define MSSQLLAYERSTATUS_DISABLED 3
+
 /* geometry format to transfer geometry column */
 #define MSSQLGEOMETRY_NATIVE 0
 #define MSSQLGEOMETRY_WKB 1
@@ -149,6 +155,8 @@ class OGRMSSQLSpatialLayer : public OGRLayer
 
     int                bIsIdentityFid;
 
+    int                nLayerStatus;
+
     int                *panFieldOrdinals;
 
     CPLErr              BuildFeatureDefn( const char *pszLayerName,
@@ -179,6 +187,9 @@ class OGRMSSQLSpatialLayer : public OGRLayer
 
     virtual int         TestCapability( const char * );
     char*               GByteArrayToHexString( const GByte* pabyData, int nLen);
+
+    void               SetLayerStatus( int nStatus ) { nLayerStatus = nStatus; }
+    int                GetLayerStatus() { return nLayerStatus; }
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
index 54c286b..250f6a3 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatialdatasource.cpp 29027 2015-04-26 18:29:41Z tamas $
+ * $Id: ogrmssqlspatialdatasource.cpp 29185 2015-05-12 10:45:44Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLSpatialDataSource class..
@@ -30,7 +30,7 @@
 
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlspatialdatasource.cpp 29027 2015-04-26 18:29:41Z tamas $");
+CPL_CVSID("$Id: ogrmssqlspatialdatasource.cpp 29185 2015-05-12 10:45:44Z tamas $");
 
 /************************************************************************/
 /*                          OGRMSSQLSpatialDataSource()                 */
@@ -180,6 +180,8 @@ int OGRMSSQLSpatialDataSource::DeleteLayer( int iLayer )
 
     CPLDebug( "MSSQLSpatial", "DeleteLayer(%s)", pszTableName );
 
+    papoLayers[iLayer]->SetSpatialIndexFlag(FALSE);
+
     delete papoLayers[iLayer];
     memmove( papoLayers + iLayer, papoLayers + iLayer + 1,
              sizeof(void *) * (nLayers - iLayer - 1) );
@@ -393,7 +395,7 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
     else
         pszFIDColumnName = CPLStrdup( pszFIDColumnNameIn );
 
-    int bFID64 = CSLFetchBoolean(papszOptions, "FID64", FALSE);
+    int bFID64 = CSLFetchBoolean(papszOptions, "FID64", FALSE);
  	const char* pszFIDType = bFID64 ? "bigint": "int";
 
     if( eType == wkbNone ) 
@@ -437,6 +439,11 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
 
     poLayer = new OGRMSSQLSpatialTableLayer( this );
 
+    if (bInTransaction)
+        poLayer->SetLayerStatus(MSSQLLAYERSTATUS_INITIAL);
+    else
+        poLayer->SetLayerStatus(MSSQLLAYERSTATUS_CREATED);
+
     poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
     poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
 
@@ -460,7 +467,7 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
         pszWKT = NULL;
     }
 
-    if( bFID64 )
+    if( bFID64 )
         poLayer->SetMetadataItem(OLMD_FID64, "YES");
     
     if (poLayer->Initialize(pszSchemaName, pszTableName, pszGeomColumn, nCoordDimension, nSRSId, pszWKT, eType) == OGRERR_FAILURE)
@@ -1388,57 +1395,77 @@ int OGRMSSQLSpatialDataSource::FetchSRSId( OGRSpatialReference * poSRS)
 
     return nSRSId;
 }
-	
-/************************************************************************/
-/*                         StartTransaction()                           */
-/*                                                                      */
-/* Should only be called by user code. Not driver internals.            */
-/************************************************************************/
-
-OGRErr OGRMSSQLSpatialDataSource::StartTransaction(CPL_UNUSED int bForce)
-{
-    if (!oSession.BeginTransaction())
-    {
+	
+/************************************************************************/
+/*                         StartTransaction()                           */
+/*                                                                      */
+/* Should only be called by user code. Not driver internals.            */
+/************************************************************************/
+
+OGRErr OGRMSSQLSpatialDataSource::StartTransaction(CPL_UNUSED int bForce)
+{
+    if (!oSession.BeginTransaction())
+    {
         CPLError( CE_Failure, CPLE_AppDefined,
-                    "Failed to start transaction: %s", oSession.GetLastError() );
-        return OGRERR_FAILURE;
-    }
-    
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                         CommitTransaction()                          */
-/*                                                                      */
-/* Should only be called by user code. Not driver internals.            */
-/************************************************************************/
-
-OGRErr OGRMSSQLSpatialDataSource::CommitTransaction()
-{
-    if (!oSession.CommitTransaction())
-     {
+                    "Failed to start transaction: %s", oSession.GetLastError() );
+        return OGRERR_FAILURE;
+    }
+    
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         CommitTransaction()                          */
+/*                                                                      */
+/* Should only be called by user code. Not driver internals.            */
+/************************************************************************/
+
+OGRErr OGRMSSQLSpatialDataSource::CommitTransaction()
+{
+    if (!oSession.CommitTransaction())
+     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                    "Failed to commit transaction: %s", oSession.GetLastError() );
-        return OGRERR_FAILURE;
-    }
-    
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                        RollbackTransaction()                         */
-/*                                                                      */
-/* Should only be called by user code. Not driver internals.            */
-/************************************************************************/
-
-OGRErr OGRMSSQLSpatialDataSource::RollbackTransaction()
-{
-    if (!oSession.RollbackTransaction())
-     {
+                    "Failed to commit transaction: %s", oSession.GetLastError() );
+
+        for( int iLayer = 0; iLayer < nLayers; iLayer++ )
+        {
+            if( papoLayers[iLayer]->GetLayerStatus() == MSSQLLAYERSTATUS_INITIAL )
+                papoLayers[iLayer]->SetLayerStatus(MSSQLLAYERSTATUS_DISABLED);
+        }
+        return OGRERR_FAILURE;
+    }
+
+    /* set the status for the newly created layers */
+    for( int iLayer = 0; iLayer < nLayers; iLayer++ )
+    {
+        if( papoLayers[iLayer]->GetLayerStatus() == MSSQLLAYERSTATUS_INITIAL )
+            papoLayers[iLayer]->SetLayerStatus(MSSQLLAYERSTATUS_CREATED);
+    }
+    
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                        RollbackTransaction()                         */
+/*                                                                      */
+/* Should only be called by user code. Not driver internals.            */
+/************************************************************************/
+
+OGRErr OGRMSSQLSpatialDataSource::RollbackTransaction()
+{
+    /* set the status for the newly created layers */
+    for( int iLayer = 0; iLayer < nLayers; iLayer++ )
+    {
+        if( papoLayers[iLayer]->GetLayerStatus() == MSSQLLAYERSTATUS_INITIAL )
+            papoLayers[iLayer]->SetLayerStatus(MSSQLLAYERSTATUS_DISABLED);
+    }
+    
+    if (!oSession.RollbackTransaction())
+     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                    "Failed to roll back transaction: %s", oSession.GetLastError() );
-        return OGRERR_FAILURE;
-    }
-    
-    return OGRERR_NONE;
+                    "Failed to roll back transaction: %s", oSession.GetLastError() );
+        return OGRERR_FAILURE;
+    }
+    
+    return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
index a27f70a..83e1b66 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatiallayer.cpp 29027 2015-04-26 18:29:41Z tamas $
+ * $Id: ogrmssqlspatiallayer.cpp 29185 2015-05-12 10:45:44Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
@@ -29,7 +29,7 @@
 
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlspatiallayer.cpp 29027 2015-04-26 18:29:41Z tamas $");
+CPL_CVSID("$Id: ogrmssqlspatiallayer.cpp 29185 2015-05-12 10:45:44Z tamas $");
 /************************************************************************/
 /*                        OGRMSSQLSpatialLayer()                        */
 /************************************************************************/
@@ -51,6 +51,7 @@ OGRMSSQLSpatialLayer::OGRMSSQLSpatialLayer()
 
     poSRS = NULL;
     nSRSId = -1; // we haven't even queried the database for it yet. 
+    nLayerStatus = MSSQLLAYERSTATUS_ORIGINAL;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
index 09aaef8..1eedd14 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatialtablelayer.cpp 29027 2015-04-26 18:29:41Z tamas $
+ * $Id: ogrmssqlspatialtablelayer.cpp 29185 2015-05-12 10:45:44Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLSpatialTableLayer class, access to an existing table.
@@ -31,7 +31,7 @@
 #include "cpl_conv.h"
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlspatialtablelayer.cpp 29027 2015-04-26 18:29:41Z tamas $");
+CPL_CVSID("$Id: ogrmssqlspatialtablelayer.cpp 29185 2015-05-12 10:45:44Z tamas $");
 
 /************************************************************************/
 /*                         OGRMSSQLAppendEscaped( )                     */
@@ -107,8 +107,9 @@ OGRMSSQLSpatialTableLayer::OGRMSSQLSpatialTableLayer( OGRMSSQLSpatialDataSource
 OGRMSSQLSpatialTableLayer::~OGRMSSQLSpatialTableLayer()
 
 {
-    if ( bNeedSpatialIndex )
+    if ( bNeedSpatialIndex && nLayerStatus == MSSQLLAYERSTATUS_CREATED )
     {
+        /* recreate spatial index */
         DropSpatialIndex();
         CreateSpatialIndex();
     }
@@ -358,7 +359,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateSpatialIndex()
         OGREnvelope oExt;
         if (GetExtent(&oExt, TRUE) != OGRERR_NONE)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Warning, CPLE_AppDefined, 
                           "Failed to get extent for spatial index." );
             return OGRERR_FAILURE;
         }
@@ -849,11 +850,11 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateField( OGRFieldDefn *poFieldIn,
     }
     if ( oField.GetDefault() != NULL && !oField.IsDefaultDriverSpecific() )
     {
-        /* process default value specifications */
-        if ( EQUAL(oField.GetDefault(), "CURRENT_TIME") )
-            oStmt.Append(" DEFAULT(CONVERT([time],getdate()))");
-        else if ( EQUAL(oField.GetDefault(), "CURRENT_DATE") )
-            oStmt.Append( " DEFAULT(CONVERT([date],getdate()))" );
+        /* process default value specifications */
+        if ( EQUAL(oField.GetDefault(), "CURRENT_TIME") )
+            oStmt.Append(" DEFAULT(CONVERT([time],getdate()))");
+        else if ( EQUAL(oField.GetDefault(), "CURRENT_DATE") )
+            oStmt.Append( " DEFAULT(CONVERT([date],getdate()))" );
         else 
             oStmt.Appendf(" DEFAULT(%s)", oField.GetDefault());
     }
@@ -1147,7 +1148,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
 /*      Form the INSERT command.                                        */
 /* -------------------------------------------------------------------- */
 
-    oStatement.Appendf( "INSERT INTO [%s].[%s] (", pszSchemaName, pszTableName );
+    oStatement.Appendf( "INSERT INTO [%s].[%s] ", pszSchemaName, pszTableName );
 
     OGRMSSQLGeometryValidator oValidator(poFeature->GetGeometryRef());
     OGRGeometry *poGeom = oValidator.GetValidGeometryRef();
@@ -1162,7 +1163,9 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     if (poGeom != NULL && pszGeomColumn != NULL)
     {
+        oStatement.Append("([");
         oStatement.Append( pszGeomColumn );
+        oStatement.Append("]");
         bNeedComma = TRUE;
     }
 
@@ -1182,7 +1185,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
             oStatement.Appendf( ", [%s]", pszFIDColumn );
         else
         {
-            oStatement.Appendf( "[%s]", pszFIDColumn );
+            oStatement.Appendf( "([%s]", pszFIDColumn );
             bNeedComma = TRUE;
         }
     }
@@ -1202,127 +1205,135 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
             oStatement.Appendf( ", [%s]", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
         else
         {
-            oStatement.Appendf( "[%s]", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
+            oStatement.Appendf( "([%s]", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
             bNeedComma = TRUE;
         }
     }
 
-    oStatement.Appendf( ") VALUES (" );
-
-    /* Set the geometry */
-    bNeedComma = FALSE;
-    if(poGeom != NULL && pszGeomColumn != NULL)
+    if (oStatement.GetCommand()[strlen(oStatement.GetCommand()) - 1] != ']')
     {
-        if (nUploadGeometryFormat == MSSQLGEOMETRY_WKB)
+        /* no fields were added */
+        oStatement.Appendf( "DEFAULT VALUES;" );
+    }
+    else
+    {
+        oStatement.Appendf( ") VALUES (" );
+
+        /* Set the geometry */
+        bNeedComma = FALSE;
+        if(poGeom != NULL && pszGeomColumn != NULL)
         {
-            int nWKBLen = poGeom->WkbSize();
-            GByte *pabyWKB = (GByte *) CPLMalloc(nWKBLen + 1);
-        
-            if( poGeom->exportToWkb( wkbNDR, pabyWKB ) == OGRERR_NONE && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
-                || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY))
+            if (nUploadGeometryFormat == MSSQLGEOMETRY_WKB)
             {
-                int nRetCode = SQLBindParameter(oStatement.GetStatement(), (SQLUSMALLINT)(bind_num + 1), 
-                    SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, 
-                    nWKBLen, 0, (SQLPOINTER)pabyWKB, nWKBLen, (SQLLEN*)&nWKBLen);
-                if ( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO )
+                int nWKBLen = poGeom->WkbSize();
+                GByte *pabyWKB = (GByte *) CPLMalloc(nWKBLen + 1);
+        
+                if( poGeom->exportToWkb( wkbNDR, pabyWKB ) == OGRERR_NONE && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
+                    || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY))
                 {
-                    if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
+                    int nRetCode = SQLBindParameter(oStatement.GetStatement(), (SQLUSMALLINT)(bind_num + 1), 
+                        SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, 
+                        nWKBLen, 0, (SQLPOINTER)pabyWKB, nWKBLen, (SQLLEN*)&nWKBLen);
+                    if ( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO )
                     {
-                        oStatement.Append( "geography::STGeomFromWKB(?" );
-                        oStatement.Appendf(",%d)", nSRSId );
+                        if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
+                        {
+                            oStatement.Append( "geography::STGeomFromWKB(?" );
+                            oStatement.Appendf(",%d)", nSRSId );
+                        }
+                        else
+                        {
+                            oStatement.Append( "geometry::STGeomFromWKB(?" );
+                            oStatement.Appendf(",%d).MakeValid()", nSRSId );
+                        }    
+                        bind_buffer[bind_num] = pabyWKB;
+                        ++bind_num;
                     }
                     else
                     {
-                        oStatement.Append( "geometry::STGeomFromWKB(?" );
-                        oStatement.Appendf(",%d).MakeValid()", nSRSId );
-                    }    
-                    bind_buffer[bind_num] = pabyWKB;
-                    ++bind_num;
+                        oStatement.Append( "null" );
+                        CPLFree(pabyWKB);
+                    }           
                 }
                 else
                 {
                     oStatement.Append( "null" );
                     CPLFree(pabyWKB);
-                }           
-            }
-            else
-            {
-                oStatement.Append( "null" );
-                CPLFree(pabyWKB);
+                }
             }
-        }
-        else if (nUploadGeometryFormat == MSSQLGEOMETRY_WKT)
-        {
-            char    *pszWKT = NULL;
-            if( poGeom->exportToWkt( &pszWKT ) == OGRERR_NONE && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
-                || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY))
+            else if (nUploadGeometryFormat == MSSQLGEOMETRY_WKT)
             {
-                size_t nLen = 0;
-                while(pszWKT[nLen] != '\0')
-                    nLen ++;
-                
-                int nRetCode = SQLBindParameter(oStatement.GetStatement(), (SQLUSMALLINT)(bind_num + 1), 
-                    SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, 
-                    nLen, 0, (SQLPOINTER)pszWKT, 0, NULL);
-                if ( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO )
+                char    *pszWKT = NULL;
+                if( poGeom->exportToWkt( &pszWKT ) == OGRERR_NONE && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
+                    || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY))
                 {
-                    if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
+                    size_t nLen = 0;
+                    while(pszWKT[nLen] != '\0')
+                        nLen ++;
+                
+                    int nRetCode = SQLBindParameter(oStatement.GetStatement(), (SQLUSMALLINT)(bind_num + 1), 
+                        SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, 
+                        nLen, 0, (SQLPOINTER)pszWKT, 0, NULL);
+                    if ( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO )
                     {
-                        oStatement.Append( "geography::STGeomFromText(?" );
-                        oStatement.Appendf(",%d)", nSRSId );
+                        if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
+                        {
+                            oStatement.Append( "geography::STGeomFromText(?" );
+                            oStatement.Appendf(",%d)", nSRSId );
+                        }
+                        else
+                        {
+                            oStatement.Append( "geometry::STGeomFromText(?" );
+                            oStatement.Appendf(",%d).MakeValid()", nSRSId );
+                        }    
+                        bind_buffer[bind_num] = pszWKT;
+                        ++bind_num;
                     }
                     else
                     {
-                        oStatement.Append( "geometry::STGeomFromText(?" );
-                        oStatement.Appendf(",%d).MakeValid()", nSRSId );
-                    }    
-                    bind_buffer[bind_num] = pszWKT;
-                    ++bind_num;
+                        oStatement.Append( "null" );
+                        CPLFree(pszWKT);
+                    }           
                 }
                 else
                 {
                     oStatement.Append( "null" );
                     CPLFree(pszWKT);
-                }           
+                }
             }
             else
-            {
                 oStatement.Append( "null" );
-                CPLFree(pszWKT);
-            }
-        }
-        else
-            oStatement.Append( "null" );
 
-        bNeedComma = TRUE;
-    }
+            bNeedComma = TRUE;
+        }
 
-    /* Set the FID */
-    if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
-    {
-        if (bNeedComma)
-            oStatement.Appendf( ", " CPL_FRMT_GIB, poFeature->GetFID() );
-        else
+        /* Set the FID */
+        if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
         {
-            oStatement.Appendf( CPL_FRMT_GIB, poFeature->GetFID() );
-            bNeedComma = TRUE;
+            if (bNeedComma)
+                oStatement.Appendf( ", " CPL_FRMT_GIB, poFeature->GetFID() );
+            else
+            {
+                oStatement.Appendf( CPL_FRMT_GIB, poFeature->GetFID() );
+                bNeedComma = TRUE;
+            }
         }
-    }
 
-    for( i = 0; i < nFieldCount; i++ )
-    {
-        if( !poFeature->IsFieldSet( i ) )
-            continue;
+        for( i = 0; i < nFieldCount; i++ )
+        {
+            if( !poFeature->IsFieldSet( i ) )
+                continue;
 
-        if (bNeedComma)
-            oStatement.Append( ", " );
-        else
-            bNeedComma = TRUE;
+            if (bNeedComma)
+                oStatement.Append( ", " );
+            else
+                bNeedComma = TRUE;
 
-        AppendFieldValue(&oStatement, poFeature, i, &bind_num, bind_buffer);
-    }
+            AppendFieldValue(&oStatement, poFeature, i, &bind_num, bind_buffer);
+        }
 
-    oStatement.Append( ");" );
+        oStatement.Append( ");" );
+    }
 
     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL && bIsIdentityFid )
         oStatement.Appendf("SET IDENTITY_INSERT [%s].[%s] OFF;", pszSchemaName, pszTableName );
diff --git a/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp b/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp
index 8b958f3..ec02e52 100644
--- a/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp
+++ b/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: filegdbindex.cpp 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: filegdbindex.cpp 29195 2015-05-14 11:27:35Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements reading of FileGDB indexes
@@ -1474,8 +1474,10 @@ int FileGDBIndexIterator::SortRows()
     if( nSortedCount == 0 )
         return FALSE;
     std::sort(panSortedRows, panSortedRows + nSortedCount);
+#ifdef nValueCountInIdx_reliable
     if( eOp == FGSO_ISNOTNULL && (int)nValueCountInIdx != nSortedCount )
         PrintError();
+#endif
     return TRUE;
 }
 
@@ -1509,8 +1511,15 @@ int FileGDBIndexIterator::GetNextRowSortedByFID()
 
 int FileGDBIndexIterator::GetRowCount()
 {
+    // The nValueCountInIdx value has been found to be unreliable when the index is built
+    // as features are inserted (and when they are not in increasing order)
+    // (with FileGDB SDK 1.3)
+    // So disable this optimization as there's no fast way to know
+    // if the value is reliable or not.
+#ifdef nValueCountInIdx_reliable
     if( eOp == FGSO_ISNOTNULL )
         return (int)nValueCountInIdx;
+#endif
 
     if( nSortedCount >= 0 )
         return nSortedCount;
diff --git a/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp
index e477dba..2eff8a1 100644
--- a/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp
+++ b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: filegdbtable.cpp 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: filegdbtable.cpp 29158 2015-05-05 21:19:37Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements reading of FileGDB tables
@@ -111,6 +111,8 @@ void FileGDBTable::Init()
     osObjectIdColName = "";
     nChSaved = -1;
     pabyTablXBlockMap = NULL;
+    nCountBlocksBeforeIBlockIdx = 0;
+    nCountBlocksBeforeIBlockValue = 0;
     bHasReadGDBIndexes = FALSE;
     nOffsetFieldDesc = 0;
     nFieldDescLength = 0;
@@ -1122,8 +1124,22 @@ vsi_l_offset FileGDBTable::GetOffsetInTableForRow(int iRow)
         if( TEST_BIT(pabyTablXBlockMap, iBlock) == 0 )
             return 0;
 
-        for(int i=0;i<iBlock;i++)
-            nCountBlocksBefore += TEST_BIT(pabyTablXBlockMap, i) != 0;
+        // In case of sequential reading, optimization to avoid recomputing
+        // the number of blocks since the beginning of the map
+        if( iBlock >= nCountBlocksBeforeIBlockIdx )
+        {
+            nCountBlocksBefore = nCountBlocksBeforeIBlockValue;
+            for(int i=nCountBlocksBeforeIBlockIdx;i<iBlock;i++)
+                nCountBlocksBefore += TEST_BIT(pabyTablXBlockMap, i) != 0;
+        }
+        else
+        {
+            nCountBlocksBefore = 0;
+            for(int i=0;i<iBlock;i++)
+                nCountBlocksBefore += TEST_BIT(pabyTablXBlockMap, i) != 0;
+        }
+        nCountBlocksBeforeIBlockIdx = iBlock;
+        nCountBlocksBeforeIBlockValue = nCountBlocksBefore;
         int iCorrectedRow = nCountBlocksBefore * 1024 + (iRow % 1024);
         VSIFSeekL(fpTableX, 16 + nTablxOffsetSize * iCorrectedRow, SEEK_SET);
     }
@@ -1155,6 +1171,46 @@ vsi_l_offset FileGDBTable::GetOffsetInTableForRow(int iRow)
 }
 
 /************************************************************************/
+/*                      GetAndSelectNextNonEmptyRow()                   */
+/************************************************************************/
+
+int FileGDBTable::GetAndSelectNextNonEmptyRow(int iRow)
+{
+    const int errorRetValue = -1;
+    returnErrorAndCleanupIf(iRow < 0 || iRow >= nTotalRecordCount, nCurRow = -1 );
+
+    while( iRow < nTotalRecordCount )
+    {
+        if( pabyTablXBlockMap != NULL && (iRow % 1024) == 0 )
+        {
+            int iBlock = iRow / 1024;
+            if( TEST_BIT(pabyTablXBlockMap, iBlock) == 0 )
+            {
+                int nBlocks = (nTotalRecordCount+1023)/1024;
+                do
+                {
+                    iBlock ++;
+                }
+                while( iBlock < nBlocks &&
+                    TEST_BIT(pabyTablXBlockMap, iBlock) == 0 );
+
+                iRow = iBlock * 1024;
+                if( iRow >= nTotalRecordCount )
+                    return -1;
+            }
+        }
+
+        if( SelectRow(iRow) )
+            return iRow;
+        if( HasGotError() )
+            return -1;
+        iRow ++;
+    }
+
+    return -1;
+}
+
+/************************************************************************/
 /*                            SelectRow()                               */
 /************************************************************************/
 
diff --git a/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h
index c250ae6..421b7bb 100644
--- a/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h
+++ b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: filegdbtable.h 28880 2015-04-09 15:18:43Z rouault $
+ * $Id: filegdbtable.h 29158 2015-05-05 21:19:37Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements reading of FileGDB tables
@@ -235,6 +235,8 @@ class FileGDBTable
         std::vector<vsi_l_offset>   anFeatureOffsets; /* MSb set marks deleted feature */
 
         GByte*                      pabyTablXBlockMap;
+        int                         nCountBlocksBeforeIBlockIdx; /* optimization */
+        int                         nCountBlocksBeforeIBlockValue; /* optimization */
 
         char                        achGUIDBuffer[32 + 6 + 1];
         int                         nChSaved;
@@ -302,6 +304,7 @@ class FileGDBTable
 
        /* Next call to SelectRow() or GetFieldValue() invalidates previously returned values */
        int                      SelectRow(int iRow);
+       int                      GetAndSelectNextNonEmptyRow(int iRow);
        int                      HasGotError() const { return bError; }
        int                      GetCurRow() const { return nCurRow; }
        int                      IsCurRowDeleted() const { return bIsDeleted; }
diff --git a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp
index ce8ebcd..3762201 100644
--- a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp
+++ b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogropenfilegdblayer.cpp 28967 2015-04-21 11:01:15Z rouault $
+ * $Id: ogropenfilegdblayer.cpp 29158 2015-05-05 21:19:37Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Open FileGDB OGR driver.
@@ -377,7 +377,7 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
             case FGTGT_MULTIPATCH: eGeomType = wkbMultiPolygon; break;
         }
 
-        if( wkbFlatten(eGeomType) != wkbFlatten(m_eGeomType) )
+        if( m_eGeomType != wkbUnknown && wkbFlatten(eGeomType) != wkbFlatten(m_eGeomType) )
         {
             CPLError(CE_Warning, CPLE_AppDefined,
                      "Inconsistency for layer geometry type");
@@ -1403,8 +1403,15 @@ OGRFeature* OGROpenFileGDBLayer::GetNextFeature()
                 {
                     return NULL;
                 }
-                if( m_poLyrTable->SelectRow(m_iCurFeat++) )
+                m_iCurFeat = m_poLyrTable->GetAndSelectNextNonEmptyRow(m_iCurFeat);
+                if( m_iCurFeat < 0 )
                 {
+                    m_bEOF = TRUE;
+                    return NULL;
+                }
+                else
+                {
+                    m_iCurFeat ++;
                     poFeature = GetCurrentFeature();
                     if( m_eSpatialIndexState == SPI_IN_BUILDING &&
                         m_iCurFeat == m_poLyrTable->GetTotalRecordCount() )
@@ -1415,11 +1422,6 @@ OGRFeature* OGROpenFileGDBLayer::GetNextFeature()
                     if( poFeature )
                         break;
                 }
-                else if( m_poLyrTable->HasGotError() )
-                {
-                    m_bEOF = TRUE;
-                    return NULL;
-                }
             }
         }
 
diff --git a/ogr/ogrsf_frmts/osm/drv_osm.html b/ogr/ogrsf_frmts/osm/drv_osm.html
index bf82d1b..3061f30 100644
--- a/ogr/ogrsf_frmts/osm/drv_osm.html
+++ b/ogr/ogrsf_frmts/osm/drv_osm.html
@@ -129,6 +129,22 @@ And to combine the above steps :
 wget -O - http://www.example.com/some.osm.bz2 | bzcat | ogr2ogr -f SQLite my.sqlite /vsistdin/
 </pre>
 
+<h2>Open options</h2>
+
+<ul>
+<li> <b>CONFIG_FILE=filename</b>: (GDAL >=2.0) Configuration filename.
+Defaults to {GDAL_DATA}/osmconf.ini.</li>
+<li> <b>USE_CUSTOM_INDEXING=YES/NO</b>: (GDAL >=2.0)
+Whether to enable custom indexing. Defaults to YES.</li>
+<li> <b>COMPRESS_NODES=YES/NO</b>: (GDAL >=2.0)
+Whether to compress nodes in temporary DB. Defaults to NO.</li>
+<li> <b>MAX_TMPFILE_SIZE=int_val</b>: (GDAL >=2.0) Maximum size in MB
+of in-memory temporary file. If it exceeds that value, it will go to disk.
+Defaults to 100.</li>
+<li> <b>INTERLEAVED_READING=YES/NO</b>: (GDAL >=2.0) Whether to
+enable interleveaved reading. Defaults to NO.</li>
+</ul>
+
 <h3>See Also</h3>
 
 <ul>
diff --git a/ogr/ogrsf_frmts/osm/ogr_osm.h b/ogr/ogrsf_frmts/osm/ogr_osm.h
index 26def96..ea86a07 100644
--- a/ogr/ogrsf_frmts/osm/ogr_osm.h
+++ b/ogr/ogrsf_frmts/osm/ogr_osm.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_osm.h 28601 2015-03-03 11:06:40Z rouault $
+ * $Id: ogr_osm.h 29242 2015-05-24 10:59:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/OpenStreeMap driver.
@@ -400,7 +400,7 @@ class OGROSMDataSource : public OGRDataSource
                                        unsigned int* pnTags, OSMTag* pasTags,
                                        OSMInfo* psInfo );
 
-    int                 ParseConf();
+    int                 ParseConf(char** papszOpenOptions);
     int                 CreateTempDB();
     int                 SetDBOptions();
     int                 SetCacheSize();
@@ -465,7 +465,7 @@ class OGROSMDataSource : public OGRDataSource
     virtual void        ReleaseResultSet( OGRLayer * poLayer );
 
 
-    int                 Open ( const char* pszFilename );
+    int                 Open ( const char* pszFilename, char** papszOpenOptions );
 
     int                 ResetReading();
     int                 ParseNextChunk(int nIdxLayer);
diff --git a/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp b/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp
index 58a5d2a..9dbaeb1 100644
--- a/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp
+++ b/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrosmdatasource.cpp 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: ogrosmdatasource.cpp 29242 2015-05-24 10:59:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGROSMDataSource class.
@@ -121,7 +121,7 @@ size_t GetMaxTotalAllocs();
 static void WriteVarInt64(GUIntBig nSVal, GByte** ppabyData);
 static void WriteVarSInt64(GIntBig nSVal, GByte** ppabyData);
 
-CPL_CVSID("$Id: ogrosmdatasource.cpp 28900 2015-04-14 09:40:34Z rouault $");
+CPL_CVSID("$Id: ogrosmdatasource.cpp 29242 2015-05-24 10:59:41Z rouault $");
 
 class DSToBeOpened
 {
@@ -2661,7 +2661,7 @@ static void OGROSMNotifyBounds( double dfXMin, double dfYMin,
 /*                                Open()                                */
 /************************************************************************/
 
-int OGROSMDataSource::Open( const char * pszFilename )
+int OGROSMDataSource::Open( const char * pszFilename, char** papszOpenOptions )
 
 {
     pszName = CPLStrdup( pszFilename );
@@ -2675,16 +2675,23 @@ int OGROSMDataSource::Open( const char * pszFilename )
     if( psParser == NULL )
         return FALSE;
 
+    if( CSLFetchBoolean(papszOpenOptions, "INTERLEAVED_READING", FALSE) )
+        bInterleavedReading = TRUE;
+
     /* The following 4 config options are only useful for debugging */
     bIndexPoints = CSLTestBoolean(CPLGetConfigOption("OSM_INDEX_POINTS", "YES"));
     bUsePointsIndex = CSLTestBoolean(CPLGetConfigOption("OSM_USE_POINTS_INDEX", "YES"));
     bIndexWays = CSLTestBoolean(CPLGetConfigOption("OSM_INDEX_WAYS", "YES"));
     bUseWaysIndex = CSLTestBoolean(CPLGetConfigOption("OSM_USE_WAYS_INDEX", "YES"));
 
-    bCustomIndexing = CSLTestBoolean(CPLGetConfigOption("OSM_USE_CUSTOM_INDEXING", "YES"));
+    bCustomIndexing = CSLTestBoolean(CSLFetchNameValueDef(
+            papszOpenOptions, "USE_CUSTOM_INDEXING",
+                        CPLGetConfigOption("OSM_USE_CUSTOM_INDEXING", "YES")));
     if( !bCustomIndexing )
         CPLDebug("OSM", "Using SQLite indexing for points");
-    bCompressNodes = CSLTestBoolean(CPLGetConfigOption("OSM_COMPRESS_NODES", "NO"));
+    bCompressNodes = CSLTestBoolean(CSLFetchNameValueDef(
+            papszOpenOptions, "COMPRESS_NODES",
+                        CPLGetConfigOption("OSM_COMPRESS_NODES", "NO")));
     if( bCompressNodes )
         CPLDebug("OSM", "Using compression for nodes DB");
 
@@ -2706,7 +2713,7 @@ int OGROSMDataSource::Open( const char * pszFilename )
     papoLayers[IDX_LYR_OTHER_RELATIONS] = new OGROSMLayer(this, IDX_LYR_OTHER_RELATIONS, "other_relations");
     papoLayers[IDX_LYR_OTHER_RELATIONS]->GetLayerDefn()->SetGeomType(wkbGeometryCollection);
 
-    if( !ParseConf() )
+    if( !ParseConf(papszOpenOptions) )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Could not parse configuration file for OSM import");
@@ -2748,7 +2755,8 @@ int OGROSMDataSource::Open( const char * pszFilename )
         return FALSE;
     }
 
-    nMaxSizeForInMemoryDBInMB = atoi(CPLGetConfigOption("OSM_MAX_TMPFILE_SIZE", "100"));
+    nMaxSizeForInMemoryDBInMB = atoi(CSLFetchNameValueDef(papszOpenOptions,
+        "MAX_TMPFILE_SIZE", CPLGetConfigOption("OSM_MAX_TMPFILE_SIZE", "100")));
     GIntBig nSize = (GIntBig)nMaxSizeForInMemoryDBInMB * 1024 * 1024;
     if (nSize < 0 || (GIntBig)(size_t)nSize != nSize)
     {
@@ -3245,9 +3253,11 @@ void OGROSMDataSource::AddComputedAttributes(int iCurLayer,
 /*                           ParseConf()                                */
 /************************************************************************/
 
-int OGROSMDataSource::ParseConf()
+int OGROSMDataSource::ParseConf(char** papszOpenOptions)
 {
-    const char *pszFilename = CPLGetConfigOption("OSM_CONFIG_FILE", NULL);
+    const char *pszFilename = 
+        CSLFetchNameValueDef(papszOpenOptions, "CONFIG_FILE",
+                             CPLGetConfigOption("OSM_CONFIG_FILE", NULL));
     if( pszFilename == NULL )
         pszFilename = CPLFindFile( "gdal", "osmconf.ini" );
     if( pszFilename == NULL )
diff --git a/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp b/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp
index acc2fbe..f9ab442 100644
--- a/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp
+++ b/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrosmdriver.cpp 27384 2014-05-24 12:28:12Z rouault $
+ * $Id: ogrosmdriver.cpp 29242 2015-05-24 10:59:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGROSMDriver class.
@@ -34,7 +34,7 @@
 
 extern "C" void CPL_DLL RegisterOGROSM();
 
-CPL_CVSID("$Id: ogrosmdriver.cpp 27384 2014-05-24 12:28:12Z rouault $");
+CPL_CVSID("$Id: ogrosmdriver.cpp 29242 2015-05-24 10:59:41Z rouault $");
 
 /************************************************************************/
 /*                      OGROSMDriverIdentify()                          */
@@ -70,7 +70,7 @@ static GDALDataset *OGROSMDriverOpen( GDALOpenInfo* poOpenInfo )
 
     OGROSMDataSource   *poDS = new OGROSMDataSource();
 
-    if( !poDS->Open( poOpenInfo->pszFilename ) )
+    if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->papszOpenOptions ) )
     {
         delete poDS;
         poDS = NULL;
@@ -103,6 +103,15 @@ void RegisterOGROSM()
 
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
+        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"<OpenOptionList>"
+"  <Option name='CONFIG_FILE' type='string' description='Configuration filename.'/>"
+"  <Option name='USE_CUSTOM_INDEXING' type='boolean' description='Whether to enable custom indexing.' default='YES'/>"
+"  <Option name='COMPRESS_NODES' type='boolean' description='Whether to compress nodes in temporary DB.' default='NO'/>"
+"  <Option name='MAX_TMPFILE_SIZE' type='int' description='Maximum size in MB of in-memory temporary file. If it exceeds that value, it will go to disk' default='100'/>"
+"  <Option name='INTERLEAVED_READING' type='boolean' description='Whether to enable interleveaved reading.' default='NO'/>"
+"</OpenOptionList>" );
+
         poDriver->pfnOpen = OGROSMDriverOpen;
         poDriver->pfnIdentify = OGROSMDriverIdentify;
 
diff --git a/ogr/ogrsf_frmts/plscenes/drv_plscenes.html b/ogr/ogrsf_frmts/plscenes/drv_plscenes.html
index 861194b..813f906 100644
--- a/ogr/ogrsf_frmts/plscenes/drv_plscenes.html
+++ b/ogr/ogrsf_frmts/plscenes/drv_plscenes.html
@@ -14,7 +14,7 @@ GDAL/OGR must be built with Curl support in order for the
 PLScenes driver to be compiled.<p>
 
 The driver supports read-only operations to list scenes and their metadata
-as a vector layer (currently only "ortho"). It can also access raster scenes.<p>
+as a vector layer per scene type ("ortho" for example). It can also access raster scenes.<p>
 
 <h2>Dataset name syntax</h2>
 
@@ -58,7 +58,7 @@ The following configuration options are available :
 <h2>Attributes</h2>
 
 The <a href="https://www.planet.com/docs/v0/scenes/#metadata">scene metadata</a>
-are retrieved into the following feature fields :<p>
+are retrieved into the following feature fields for the "ortho" layer :<p>
 
 <table border="1">
 <tr><th>Name</th><th>Type</th><th>Description</th></tr>
@@ -92,6 +92,8 @@ are retrieved into the following feature fields :<p>
 <tr><td>sun.local_time_of_day</td><td>Real</td><td>The local sun time at the imaged location at the time of capture (0-24).</td></tr>
 </table>
 
+For other layers / scene types, additional attributes may be retrieved.<p>
+
 <h3>Geometry</h3>
 
 The footprint of each scene is reported as a MultiPolygon with a longitude/latitude
diff --git a/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h b/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h
index d771b00..a5b6d77 100644
--- a/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h
+++ b/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_plscenes.h 28963 2015-04-20 19:55:40Z rouault $
+ * $Id: ogr_plscenes.h 29164 2015-05-06 15:01:37Z rouault $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  PLScenes driver interface
@@ -62,6 +62,7 @@ class OGRPLScenesDataset: public GDALDataset
 
         virtual int         GetLayerCount() { return nLayers; }
         virtual OGRLayer   *GetLayer(int idx);
+        virtual OGRLayer   *GetLayerByName(const char* pszName);
         virtual OGRLayer   *ExecuteSQL( const char *pszSQLCommand,
                                         OGRGeometry *poSpatialFilter,
                                         const char *pszDialect );
@@ -108,8 +109,9 @@ class OGRPLScenesLayer: public OGRLayer
 
     public:
                             OGRPLScenesLayer(OGRPLScenesDataset* poDS,
-                                         const char* pszName,
-                                         const char* pszBaseURL);
+                                             const char* pszName,
+                                             const char* pszBaseURL,
+                                             json_object* poObjCount10 = NULL);
                            ~OGRPLScenesLayer();
 
         virtual void            ResetReading();
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp
index 85e9241..930d352 100644
--- a/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp
+++ b/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrplscenesdataset.cpp 29085 2015-04-30 19:40:11Z rouault $
+ * $Id: ogrplscenesdataset.cpp 29164 2015-05-06 15:01:37Z rouault $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  Implements OGRPLScenesDataset
@@ -31,7 +31,7 @@
 
 // g++ -g -Wall -fPIC -shared -o ogr_PLSCENES.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/plscene ogr/ogrsf_frmts/plscenes/*.c* -L. -lgdal -Iogr/ogrsf_frmts/geojson -Iogr/ogrsf_frmts/geojson/libjson 
 
-CPL_CVSID("$Id: ogrplscenesdataset.cpp 29085 2015-04-30 19:40:11Z rouault $");
+CPL_CVSID("$Id: ogrplscenesdataset.cpp 29164 2015-05-06 15:01:37Z rouault $");
 
 extern "C" void RegisterOGRPLSCENES();
 
@@ -76,6 +76,34 @@ OGRLayer *OGRPLScenesDataset::GetLayer(int idx)
     return papoLayers[idx];
 }
 
+/************************************************************************/
+/*                          GetLayerByName()                            */
+/************************************************************************/
+
+OGRLayer *OGRPLScenesDataset::GetLayerByName(const char* pszName)
+{
+    OGRLayer* poLayer = GDALDataset::GetLayerByName(pszName);
+    if( poLayer != NULL )
+        return poLayer;
+
+    CPLString osURL;
+    osURL = osBaseURL;
+    osURL += pszName;
+    osURL += "/";
+    json_object* poObj = RunRequest( (osURL + CPLString("?count=10")).c_str() );
+    if( poObj == NULL )
+        return NULL;
+
+    OGRPLScenesLayer* poPLLayer = new OGRPLScenesLayer(this, pszName, osURL, poObj);
+    papoLayers = (OGRPLScenesLayer**) CPLRealloc(papoLayers,
+                                sizeof(OGRPLScenesLayer*) * (nLayers + 1));
+    papoLayers[nLayers ++] = poPLLayer;
+
+    json_object_put(poObj);
+
+    return poPLLayer;
+}
+
 /***********************************************************************/
 /*                            ExecuteSQL()                             */
 /***********************************************************************/
@@ -502,8 +530,17 @@ GDALDataset* OGRPLScenesDataset::Open(GDALOpenInfo* poOpenInfo)
     {
         if( it.val != NULL && json_object_get_type(it.val) == json_type_string )
         {
-            OGRPLScenesLayer* poLayer = new OGRPLScenesLayer(poDS, it.key,
-                                                     json_object_get_string(it.val));
+            const char* pszSceneType = it.key;
+            const char* pszSceneTypeURL = json_object_get_string(it.val);
+            json_object* poObj = NULL;
+            if( !EQUAL(pszSceneType, "ortho") )
+                poObj = poDS->RunRequest( (CPLString(pszSceneTypeURL) + CPLString("?count=10")).c_str() );
+
+            OGRPLScenesLayer* poLayer = new OGRPLScenesLayer(poDS, pszSceneType, pszSceneTypeURL, poObj);
+
+            if( poObj )
+                json_object_put(poObj);
+
             poDS->papoLayers = (OGRPLScenesLayer**) CPLRealloc(poDS->papoLayers,
                                         sizeof(OGRPLScenesLayer*) * (poDS->nLayers + 1));
             poDS->papoLayers[poDS->nLayers ++] = poLayer;
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp b/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp
index 4383ad3..72d92e6 100644
--- a/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp
+++ b/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrplsceneslayer.cpp 28928 2015-04-17 10:24:19Z rouault $
+ * $Id: ogrplsceneslayer.cpp 29164 2015-05-06 15:01:37Z rouault $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  Implements OGRPLScenesLayer
@@ -28,8 +28,9 @@
  ****************************************************************************/
 
 #include "ogr_plscenes.h"
+#include <algorithm>
 
-CPL_CVSID("$Id: ogrplsceneslayer.cpp 28928 2015-04-17 10:24:19Z rouault $");
+CPL_CVSID("$Id: ogrplsceneslayer.cpp 29164 2015-05-06 15:01:37Z rouault $");
 
 typedef struct
 {
@@ -67,13 +68,31 @@ static const PLAttribute apsAttrs[] = {
     { "sun.local_time_of_day",            OFTReal },
 };
 
+static bool OGRPLScenesLayerFieldNameComparator(const CPLString& osFirst,
+                                                const CPLString& osSecond)
+{
+    const char* pszUnderscore1 = strrchr(osFirst.c_str(), '_');
+    const char* pszUnderscore2 = strrchr(osSecond.c_str(), '_');
+    int val1, val2;
+    if( pszUnderscore1 && pszUnderscore2 &&
+        (CPLString(osFirst).substr(0, pszUnderscore1-osFirst.c_str()) ==
+         CPLString(osSecond).substr(0, pszUnderscore2-osSecond.c_str())) &&
+        sscanf(pszUnderscore1 + 1, "%d", &val1) == 1 &&
+        sscanf(pszUnderscore2 + 1, "%d", &val2) == 1 )
+    {
+        return val1 < val2;
+    }
+    return osFirst < osSecond;
+}
+
 /************************************************************************/
 /*                           OGRPLScenesLayer()                         */
 /************************************************************************/
 
 OGRPLScenesLayer::OGRPLScenesLayer(OGRPLScenesDataset* poDS,
-                           const char* pszName,
-                           const char* pszBaseURL)
+                                   const char* pszName,
+                                   const char* pszBaseURL,
+                                   json_object* poObjCount10)
 {
     this->poDS = poDS;
     osBaseURL = pszBaseURL;
@@ -99,6 +118,36 @@ OGRPLScenesLayer::OGRPLScenesLayer(OGRPLScenesDataset* poDS,
     bAcquiredAscending = -1;
     bFilterMustBeClientSideEvaluated = FALSE;
     ResetReading();
+    
+    if( poObjCount10 != NULL )
+    {
+        json_object* poCount = json_object_object_get(poObjCount10, "count");
+        if( poCount != NULL )
+            nFeatureCount = MAX(0, json_object_get_int64(poCount));
+
+        OGRGeoJSONDataSource* poTmpDS = new OGRGeoJSONDataSource();
+        OGRGeoJSONReader oReader;
+        oReader.SetFlattenNestedAttributes(true, '.');
+        oReader.ReadLayer( poTmpDS, "layer", poObjCount10 );
+        OGRLayer* poTmpLayer = poTmpDS->GetLayer(0);
+        if( poTmpLayer )
+        {
+            OGRFeatureDefn* poTmpFDefn = poTmpLayer->GetLayerDefn();
+            std::vector<CPLString> aosNewFields;
+            for(int i=0;i<poTmpFDefn->GetFieldCount();i++)
+            {
+                if( poFeatureDefn->GetFieldIndex(poTmpFDefn->GetFieldDefn(i)->GetNameRef()) < 0 )
+                    aosNewFields.push_back(poTmpFDefn->GetFieldDefn(i)->GetNameRef());
+            }
+            std::sort(aosNewFields.begin(), aosNewFields.end(), OGRPLScenesLayerFieldNameComparator);
+            for(int i=0;i<(int)aosNewFields.size();i++)
+            {
+                OGRFieldDefn oField(poTmpFDefn->GetFieldDefn(poTmpFDefn->GetFieldIndex(aosNewFields[i])));
+                poFeatureDefn->AddFieldDefn(&oField);
+            }
+        }
+        delete poTmpDS;
+    }
 }
 
 /************************************************************************/
@@ -551,7 +600,7 @@ OGRFeature* OGRPLScenesLayer::GetNextRawFeature()
         OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(i);
         OGRFieldType eType = poFieldDefn->GetType();
         int iSrcField = poGeoJSONFeature->GetFieldIndex(poFieldDefn->GetNameRef());
-        if( iSrcField >= 0 )
+        if( iSrcField >= 0 && poGeoJSONFeature->IsFieldSet(iSrcField) )
         {
             if( eType == OFTInteger )
                 poFeature->SetField(i,
diff --git a/ogr/ogrsf_frmts/shape/shape2ogr.cpp b/ogr/ogrsf_frmts/shape/shape2ogr.cpp
index 4898dd7..3a22036 100644
--- a/ogr/ogrsf_frmts/shape/shape2ogr.cpp
+++ b/ogr/ogrsf_frmts/shape/shape2ogr.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: shape2ogr.cpp 28900 2015-04-14 09:40:34Z rouault $
+ * $Id: shape2ogr.cpp 29234 2015-05-22 19:17:03Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements translation of Shapefile shapes into OGR
@@ -32,7 +32,7 @@
 #include "ogrshape.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: shape2ogr.cpp 28900 2015-04-14 09:40:34Z rouault $");
+CPL_CVSID("$Id: shape2ogr.cpp 29234 2015-05-22 19:17:03Z rouault $");
 
 /************************************************************************/
 /*                        RingStartEnd                                  */
@@ -1078,6 +1078,8 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
         CPLError( CE_Failure, CPLE_AppDefined, 
                   "Attempt to read shape with feature id (%d), but it is marked deleted.",
                   iShape );
+        if( psShape != NULL )
+            SHPDestroyObject(psShape);
         return NULL;
     }
 
diff --git a/ogr/ogrsf_frmts/wfs/drv_wfs.html b/ogr/ogrsf_frmts/wfs/drv_wfs.html
index 1a4a016..cd6ba10 100644
--- a/ogr/ogrsf_frmts/wfs/drv_wfs.html
+++ b/ogr/ogrsf_frmts/wfs/drv_wfs.html
@@ -212,8 +212,20 @@ interfaces.<p>
 
 The following options are available:
 <ul>
+<li><b>URL</b>=url: URL to the WFS server endpoint. Required when using the
+"WFS:" string as the connection string.</li>
 <li><b>TRUST_CAPABILITIES_BOUNDS</b>=YES/NO: Whether to trust layer bounds
 declared in GetCapabilities response, for faster GetExtent() runtime. Defaults to NO</li>
+<li> <b>EMPTY_AS_NULL=YES/NO</b>: (GDAL >=2.0) By default (EMPTY_AS_NULL=YES),
+fields with empty content will be reported as being NULL, instead of being an empty
+string. This is the historic behaviour. However this will prevent such fields to
+be declared as not-nullable if the application schema declared them as mandatory.
+So this option can be set to NO to have both empty strings being report as such,
+and mandatory fields being reported as not nullable.</li>
+<li> <b>INVERT_AXIS_ORDER_IF_LAT_LONG=YES/NO</b>: (GDAL >=2.0) Whether to
+present SRS and coordinate ordering in traditional GIS order. Defaults to YES.</li>
+<li> <b>CONSIDER_EPSG_AS_URN=YES/NO/AUTO</b>: (GDAL >=2.0) Whether to
+consider srsName like EPSG:XXXX as respecting EPSG axis order. Defaults to AUTO.</li>
 </ul>
 
 <h2>Examples</h2>
diff --git a/ogr/ogrsf_frmts/wfs/ogr_wfs.h b/ogr/ogrsf_frmts/wfs/ogr_wfs.h
index c5ac0a7..59b93ca 100644
--- a/ogr/ogrsf_frmts/wfs/ogr_wfs.h
+++ b/ogr/ogrsf_frmts/wfs/ogr_wfs.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_wfs.h 29028 2015-04-26 21:19:29Z rouault $
+ * $Id: ogr_wfs.h 29241 2015-05-24 10:58:54Z rouault $
  *
  * Project:  WFS Translator
  * Purpose:  Definition of classes for OGR WFS driver.
@@ -324,6 +324,11 @@ class OGRWFSDataSource : public OGRDataSource
     OGRLayer           *poLayerGetCapabilitiesLayer;
 
     int                 bKeepLayerNamePrefix;
+    
+    int                 bEmptyAsNull;
+    
+    int                 bInvertAxisOrderIfLatLong;
+    CPLString           osConsiderEPSGAsURN;
 
     CPLHTTPResult*      SendGetCapabilities(const char* pszBaseURL,
                                             CPLString& osTypeName);
@@ -384,6 +389,10 @@ class OGRWFSDataSource : public OGRDataSource
 
     int                         GetKeepLayerNamePrefix() { return bKeepLayerNamePrefix; }
     const CPLString&            GetBaseURL() { return osBaseURL; }
+    
+    int                         IsEmptyAsNull() const { return bEmptyAsNull; }
+    int                         InvertAxisOrderIfLatLong() const { return bInvertAxisOrderIfLatLong; }
+    const CPLString&            GetConsiderEPSGAsURN() const { return osConsiderEPSGAsURN; }
 
     virtual char**              GetMetadataDomainList();
     virtual char**              GetMetadata( const char * pszDomain = "" );
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
index 03a66ea..a6cb4a4 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrwfsdatasource.cpp 29028 2015-04-26 21:19:29Z rouault $
+ * $Id: ogrwfsdatasource.cpp 29241 2015-05-24 10:58:54Z rouault $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGRWFSDataSource class
@@ -37,7 +37,7 @@
 #include "swq.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrwfsdatasource.cpp 29028 2015-04-26 21:19:29Z rouault $");
+CPL_CVSID("$Id: ogrwfsdatasource.cpp 29241 2015-05-24 10:58:54Z rouault $");
 
 #define DEFAULT_BASE_START_INDEX     0
 #define DEFAULT_PAGE_SIZE            100
@@ -192,6 +192,9 @@ OGRWFSDataSource::OGRWFSDataSource()
     bKeepLayerNamePrefix = FALSE;
     apszGetCapabilities[0] = NULL;
     apszGetCapabilities[1] = NULL;
+    bEmptyAsNull = TRUE;
+    
+    bInvertAxisOrderIfLatLong = TRUE;
 }
 
 /************************************************************************/
@@ -899,6 +902,8 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
     CPLString osTypeName;
     const char* pszBaseURL = NULL;
 
+    bEmptyAsNull = CSLFetchBoolean(papszOpenOptions, "EMPTY_AS_NULL", TRUE);
+
     if (psXML == NULL)
     {
         if (!EQUALN(pszFilename, "WFS:", 4) &&
@@ -1095,8 +1100,14 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
         }
     }
 
-    int bInvertAxisOrderIfLatLong = CSLTestBoolean(CPLGetConfigOption(
-                                  "GML_INVERT_AXIS_ORDER_IF_LAT_LONG", "YES"));
+    bInvertAxisOrderIfLatLong =
+        CSLTestBoolean(CSLFetchNameValueDef(papszOpenOptions,
+            "INVERT_AXIS_ORDER_IF_LAT_LONG",
+            CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", "YES")));
+    osConsiderEPSGAsURN =
+        CSLFetchNameValueDef(papszOpenOptions,
+            "CONSIDER_EPSG_AS_URN",
+            CPLGetConfigOption("GML_CONSIDER_EPSG_AS_URN", "AUTO"));
 
     CPLXMLNode* psStrippedXML = CPLCloneXMLTree(psXML);
     CPLStripXMLNamespace( psStrippedXML, NULL, TRUE );
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp
index 9d7f8d0..4101af4 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp
@@ -32,7 +32,7 @@
 
 // g++ -fPIC -g -Wall ogr/ogrsf_frmts/wfs/*.cpp -shared -o ogr_WFS.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/gml -Iogr/ogrsf_frmts/wfs -L. -lgdal
 
-CPL_CVSID("$Id: ogrwfsdriver.cpp 29019 2015-04-25 20:34:19Z rouault $");
+CPL_CVSID("$Id: ogrwfsdriver.cpp 29241 2015-05-24 10:58:54Z rouault $");
 
 extern "C" void RegisterOGRWFS();
 
@@ -106,6 +106,13 @@ void RegisterOGRWFS()
 "<OpenOptionList>"
 "  <Option name='URL' type='string' description='URL to the WFS server endpoint' required='true'/>"
 "  <Option name='TRUST_CAPABILITIES_BOUNDS' type='boolean' description='Whether to trust layer bounds declared in GetCapabilities response' default='NO'/>"
+"  <Option name='EMPTY_AS_NULL' type='boolean' description='Force empty fields to be reported as NULL. Set to NO so that not-nullable fields can be exposed' default='YES'/>"
+"  <Option name='INVERT_AXIS_ORDER_IF_LAT_LONG' type='boolean' description='Whether to present SRS and coordinate ordering in traditional GIS order' default='YES'/>"
+"  <Option name='CONSIDER_EPSG_AS_URN' type='string-select' description='Whether to consider srsName like EPSG:XXXX as respecting EPSG axis order' default='AUTO'>"
+"    <Value>AUTO</Value>"
+"    <Value>YES</Value>"
+"    <Value>NO</Value>"
+"  </Option>"
 "</OpenOptionList>" );
 
         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp b/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
index 32a89d7..23c5e89 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrwfslayer.cpp 29028 2015-04-26 21:19:29Z rouault $
+ * $Id: ogrwfslayer.cpp 29241 2015-05-24 10:58:54Z rouault $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGRWFSLayer class.
@@ -34,7 +34,7 @@
 #include "cpl_http.h"
 #include "parsexsd.h"
 
-CPL_CVSID("$Id: ogrwfslayer.cpp 29028 2015-04-26 21:19:29Z rouault $");
+CPL_CVSID("$Id: ogrwfslayer.cpp 29241 2015-05-24 10:58:54Z rouault $");
 
 
 /************************************************************************/
@@ -377,7 +377,8 @@ OGRFeatureDefn* OGRWFSLayer::BuildLayerDefnFromFeatureClass(GMLFeatureClass* poC
             oField.SetSubType(OFSTInt16);
         else if( poProperty->GetType() == GMLPT_Float) 
             oField.SetSubType(OFSTFloat32);
-        oField.SetNullable(poProperty->IsNullable());
+        if( !poDS->IsEmptyAsNull() )
+            oField.SetNullable(poProperty->IsNullable());
 
         poFDefn->AddFieldDefn( &oField );
     }
@@ -738,8 +739,23 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
         }
 
         const char* const apszAllowedDrivers[] = { "GML", NULL };
-        const char* apszOpenOptions[2] = { NULL, NULL };
+        const char* apszOpenOptions[5] = { NULL, NULL, NULL, NULL, NULL };
         apszOpenOptions[0] = CPLSPrintf("XSD=%s", osXSDFileName.c_str());
+        apszOpenOptions[1] = CPLSPrintf("EMPTY_AS_NULL=%s", poDS->IsEmptyAsNull() ? "YES" : "NO");
+        int iGMLOOIdex = 2;
+        if( CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", NULL) == NULL )
+        {
+            apszOpenOptions[iGMLOOIdex] = CPLSPrintf("INVERT_AXIS_ORDER_IF_LAT_LONG=%s",
+                                    poDS->InvertAxisOrderIfLatLong() ? "YES" : "NO");
+            iGMLOOIdex ++;
+        }
+        if( CPLGetConfigOption("GML_CONSIDER_EPSG_AS_URN", NULL) == NULL )
+        {
+            apszOpenOptions[iGMLOOIdex] = CPLSPrintf("CONSIDER_EPSG_AS_URN=%s",
+                                            poDS->GetConsiderEPSGAsURN().c_str());
+            iGMLOOIdex ++;
+        }
+
         GDALDataset* poGML_DS = (GDALDataset*)
                 GDALOpenEx(pszStreamingName, GDAL_OF_VECTOR, apszAllowedDrivers,
                            apszOpenOptions, NULL);
@@ -947,10 +963,29 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
 
     CPLHTTPDestroyResult(psResult);
 
-    OGRDataSource* poDS;
+    const char* const * papszOpenOptions = NULL;
+    const char* apszGMLOpenOptions[3] = { NULL, NULL, NULL };
+    int iGMLOOIdex = 0;
+    if( CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", NULL) == NULL )
+    {
+        apszGMLOpenOptions[iGMLOOIdex] = CPLSPrintf("INVERT_AXIS_ORDER_IF_LAT_LONG=%s",
+                                poDS->InvertAxisOrderIfLatLong() ? "YES" : "NO");
+        iGMLOOIdex ++;
+    }
+    if( CPLGetConfigOption("GML_CONSIDER_EPSG_AS_URN", NULL) == NULL )
+    {
+        apszGMLOpenOptions[iGMLOOIdex] = CPLSPrintf("CONSIDER_EPSG_AS_URN=%s",
+                                        poDS->GetConsiderEPSGAsURN().c_str());
+        iGMLOOIdex ++;
+    }
+
+    GDALDriverH hDrv = GDALIdentifyDriver(osTmpFileName, NULL);
+    if( hDrv != NULL && hDrv == GDALGetDriverByName("GML") )
+        papszOpenOptions = apszGMLOpenOptions;
 
-    poDS = (OGRDataSource*) OGROpen(osTmpFileName, FALSE, NULL);
-    if (poDS == NULL && (bZIP || bIsMultiPart))
+    GDALDataset* poPageDS = (GDALDataset*) GDALOpenEx(osTmpFileName,
+                                GDAL_OF_VECTOR, NULL, papszOpenOptions, NULL);
+    if (poPageDS == NULL && (bZIP || bIsMultiPart))
     {
         char** papszFileList = VSIReadDir(osTmpFileName);
         int i;
@@ -958,15 +993,19 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
         {
             CPLString osFullFilename =
                     CPLFormFilename( osTmpFileName, papszFileList[i], NULL );
-            poDS = (OGRDataSource*) OGROpen(osFullFilename, FALSE, NULL);
-            if (poDS != NULL)
+            GDALDriverH hDrv = GDALIdentifyDriver(osFullFilename, NULL);
+            if( hDrv != NULL && hDrv == GDALGetDriverByName("GML") )
+                papszOpenOptions = apszGMLOpenOptions;
+            poPageDS = (GDALDataset*) GDALOpenEx(osFullFilename,
+                                GDAL_OF_VECTOR, NULL, papszOpenOptions, NULL);
+            if (poPageDS != NULL)
                 break;
         }
 
         CSLDestroy( papszFileList );
     }
 
-    if (poDS == NULL)
+    if (poPageDS == NULL)
     {
         if (pabyData != NULL && !bJSON && !bZIP &&
             strstr((const char*)pabyData, "<wfs:FeatureCollection") == NULL &&
@@ -980,14 +1019,14 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
         return NULL;
     }
 
-    OGRLayer* poLayer = poDS->GetLayer(0);
+    OGRLayer* poLayer = poPageDS->GetLayer(0);
     if (poLayer == NULL)
     {
-        OGRDataSource::DestroyDataSource(poDS);
+        GDALClose(poPageDS);
         return NULL;
     }
 
-    return poDS;
+    return poPageDS;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
index c73ab53..f993629 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
@@ -30,7 +30,7 @@
 #include "ogr_xplane_apt_reader.h"
 #include "ogr_xplane_geo_utils.h"
 
-CPL_CVSID("$Id: ogr_xplane_apt_reader.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogr_xplane_apt_reader.cpp 29211 2015-05-19 19:40:57Z rouault $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateAptFileReader                       */
@@ -47,6 +47,9 @@ OGRXPlaneReader* OGRXPlaneCreateAptFileReader( OGRXPlaneDataSource* poDataSource
 /************************************************************************/
 OGRXPlaneAptReader::OGRXPlaneAptReader()
 {
+    poDataSource = NULL;
+    nVersion = APT_V_UNKNOWN;
+
     poAPTLayer = NULL;
     poRunwayLayer = NULL;
     poRunwayThresholdLayer = NULL;
@@ -65,6 +68,7 @@ OGRXPlaneAptReader::OGRXPlaneAptReader()
     poAPTWindsockLayer = NULL;
     poTaxiwaySignLayer = NULL;
     poVASI_PAPI_WIGWAG_Layer = NULL;
+    poTaxiLocationLayer = NULL;
     
     Rewind();
 }
@@ -73,8 +77,11 @@ OGRXPlaneAptReader::OGRXPlaneAptReader()
 /*                         OGRXPlaneAptReader()                         */
 /************************************************************************/
 
-OGRXPlaneAptReader::OGRXPlaneAptReader( OGRXPlaneDataSource* poDataSource )
+OGRXPlaneAptReader::OGRXPlaneAptReader( OGRXPlaneDataSource* poDataSourceIn )
 {
+    poDataSource = poDataSourceIn;
+    nVersion = APT_V_UNKNOWN;
+
     poAPTLayer = new OGRXPlaneAPTLayer();
     poRunwayLayer = new OGRXPlaneRunwayLayer();
     poRunwayThresholdLayer = new OGRXPlaneRunwayThresholdLayer();
@@ -93,6 +100,7 @@ OGRXPlaneAptReader::OGRXPlaneAptReader( OGRXPlaneDataSource* poDataSource )
     poAPTWindsockLayer = new OGRXPlaneAPTWindsockLayer();
     poTaxiwaySignLayer = new OGRXPlaneTaxiwaySignLayer();
     poVASI_PAPI_WIGWAG_Layer = new OGRXPlane_VASI_PAPI_WIGWAG_Layer();
+    poTaxiLocationLayer = NULL;
 
     poDataSource->RegisterLayer(poAPTLayer);
     poDataSource->RegisterLayer(poRunwayLayer);
@@ -143,6 +151,7 @@ OGRXPlaneReader* OGRXPlaneAptReader::CloneForLayer(OGRXPlaneLayer* poLayer)
     SET_IF_INTEREST_LAYER(poAPTWindsockLayer);
     SET_IF_INTEREST_LAYER(poTaxiwaySignLayer);
     SET_IF_INTEREST_LAYER(poVASI_PAPI_WIGWAG_Layer);
+    SET_IF_INTEREST_LAYER(poTaxiLocationLayer);
 
     if (pszFilename)
     {
@@ -181,9 +190,25 @@ void OGRXPlaneAptReader::Rewind()
 
 int OGRXPlaneAptReader::IsRecognizedVersion( const char* pszVersionString)
 {
-    return EQUALN(pszVersionString, "850 Version", 11) ||
-           EQUALN(pszVersionString, "810 Version", 11) ||
-           EQUALN(pszVersionString, "1000 Version", 12);
+    if (EQUALN(pszVersionString, "810 Version", 11))
+        nVersion = APT_V_810;
+    else if (EQUALN(pszVersionString, "850 Version", 11))
+        nVersion = APT_V_850;
+    else if (EQUALN(pszVersionString, "1000 Version", 12))
+        nVersion = APT_V_1000;
+    else
+        nVersion = APT_V_UNKNOWN;
+
+    if (nVersion == APT_V_1000)
+    {
+        if (poDataSource)
+        {
+            poTaxiLocationLayer = new OGRXPlaneTaxiLocationLayer();
+            poDataSource->RegisterLayer(poTaxiLocationLayer);
+        }
+    }
+
+    return nVersion != APT_V_UNKNOWN;
 }
 
 /************************************************************************/
@@ -342,7 +367,13 @@ void OGRXPlaneAptReader::Read()
                         ParseAPTBoundary();
                     break;
 
+                case APT_TAXI_LOCATION:
+                    if (poTaxiLocationLayer)
+                        ParseTaxiLocation();
+                    break;
+
                 default:
+                    CPLDebug("XPLANE", "Line %d, Unknown code : %d", nLineNumber, nType);
                     break;
             }
         } while(bResumeLine);
@@ -1788,6 +1819,32 @@ void OGRXPlaneAptReader::ParseVasiPapiWigWagRecord()
 }
 
 /************************************************************************/
+/*                          ParseTaxiLocation                           */
+/************************************************************************/
+
+void OGRXPlaneAptReader::ParseTaxiLocation()
+{
+    double dfLat, dfLon;
+    double dfTrueHeading;
+    CPLString osLocationType;
+    CPLString osAirplaneTypes;
+    CPLString osName;
+
+    RET_IF_FAIL(assertMinCol(7));
+
+    RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
+    RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 3, "heading"));
+    osLocationType = papszTokens[4];
+    osAirplaneTypes = papszTokens[5];
+    osName = readStringUntilEnd(6);
+
+    if (poTaxiLocationLayer)
+        poTaxiLocationLayer->AddFeature(osAptICAO, dfLat, dfLon,
+                                        dfTrueHeading, osLocationType,
+                                        osAirplaneTypes, osName);
+}
+
+/************************************************************************/
 /*                         OGRXPlaneAPTLayer()                          */
 /************************************************************************/
 
@@ -3106,3 +3163,57 @@ OGRFeature*
 
     return poFeature;
 }
+
+/************************************************************************/
+/*                       OGRXPlaneTaxiLocationLayer()                   */
+/************************************************************************/
+
+OGRXPlaneTaxiLocationLayer::OGRXPlaneTaxiLocationLayer() : OGRXPlaneLayer("TaxiLocation")
+{
+    poFeatureDefn->SetGeomType( wkbPoint );
+
+    OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
+    oFieldAptICAO.SetWidth( 4 );
+    poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
+
+    OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
+    oFieldTrueHeading.SetWidth( 6 );
+    oFieldTrueHeading.SetPrecision( 2 );
+    poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
+
+    OGRFieldDefn oFieldLocationType("location_type", OFTString );
+    poFeatureDefn->AddFieldDefn( &oFieldLocationType );
+
+    OGRFieldDefn oFieldAirplaneTypes("airplane_types", OFTString );
+    poFeatureDefn->AddFieldDefn( &oFieldAirplaneTypes );
+    
+    OGRFieldDefn oFieldName("name", OFTString );
+    poFeatureDefn->AddFieldDefn( &oFieldName );
+}
+
+/************************************************************************/
+/*                           AddFeature()                               */
+/************************************************************************/
+
+OGRFeature*
+     OGRXPlaneTaxiLocationLayer::AddFeature (const char* pszAptICAO,
+                                             double dfLat,
+                                             double dfLon,
+                                             double dfHeading,
+                                             const char* pszLocationType,
+                                             const char* pszAirplaneTypes,
+                                             const char* pszName)
+{
+    int nCount = 0;
+    OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+    poFeature->SetField( nCount++, pszAptICAO );
+    poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
+    poFeature->SetField( nCount++, dfHeading );
+    poFeature->SetField( nCount++, pszLocationType );
+    poFeature->SetField( nCount++, pszAirplaneTypes );
+    poFeature->SetField( nCount++, pszName );
+
+    RegisterFeature(poFeature);
+
+    return poFeature;
+}
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h
index aeab6eb..97d13c9 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h
@@ -537,14 +537,38 @@ class OGRXPlane_VASI_PAPI_WIGWAG_Layer : public OGRXPlaneLayer
                                    double dfVisualGlidePathAngle);
 };
 
+/************************************************************************/
+/*                       OGRXPlaneTaxiLocationLayer                     */
+/************************************************************************/
+
+class OGRXPlaneTaxiLocationLayer : public OGRXPlaneLayer
+{
+  public:
+                        OGRXPlaneTaxiLocationLayer();
+
+    OGRFeature*         AddFeature(const char* pszAptICAO,
+                                   double dfLat,
+                                   double dfLon,
+                                   double dfHeading,
+                                   const char* pszLocationType,
+                                   const char* pszAirplaneTypes,
+                                   const char* pszName);
+};
 
+typedef enum
+{
+    APT_V_UNKNOWN = 0,
+    APT_V_810 = 810,
+    APT_V_850 = 850,
+    APT_V_1000 = 1000,
+} AptVersion;
 
 enum
 {
     APT_AIRPORT_HEADER         = 1,
     APT_RUNWAY_TAXIWAY_V_810   = 10,
     APT_TOWER                  = 14,
-    APT_STARTUP_LOCATION       = 15,
+    APT_STARTUP_LOCATION       = 15, /* deprecated in V_1000 */
     APT_SEAPLANE_HEADER        = 16,
     APT_HELIPORT_HEADER        = 17,
     APT_LIGHT_BEACONS          = 18,
@@ -570,6 +594,7 @@ enum
     APT_NODE_END_WITH_BEZIER   = 116,
     APT_LINEAR_HEADER          = 120,
     APT_BOUNDARY_HEADER        = 130,
+    APT_TAXI_LOCATION          = 1300, /* added in V_1000 */
 };
 
 
@@ -581,6 +606,8 @@ enum
 class OGRXPlaneAptReader : public OGRXPlaneReader
 {
     private:
+        OGRXPlaneDataSource*                poDataSource;
+
         OGRXPlaneAPTLayer*                  poAPTLayer;
         OGRXPlaneRunwayLayer*               poRunwayLayer;
         OGRXPlaneStopwayLayer*              poStopwayLayer;
@@ -599,6 +626,9 @@ class OGRXPlaneAptReader : public OGRXPlaneReader
         OGRXPlaneAPTWindsockLayer*          poAPTWindsockLayer;
         OGRXPlaneTaxiwaySignLayer*          poTaxiwaySignLayer;
         OGRXPlane_VASI_PAPI_WIGWAG_Layer*   poVASI_PAPI_WIGWAG_Layer;
+        OGRXPlaneTaxiLocationLayer*         poTaxiLocationLayer;
+
+        AptVersion nVersion;
 
         int       bAptHeaderFound;
         double    dfElevation;
@@ -635,6 +665,7 @@ class OGRXPlaneAptReader : public OGRXPlaneReader
         void    ParseWindsockRecord();
         void    ParseTaxiwaySignRecord();
         void    ParseVasiPapiWigWagRecord();
+        void    ParseTaxiLocation();
 
         OGRGeometry* FixPolygonTopology(OGRPolygon& polygon);
         int     ParsePolygonalGeometry(OGRGeometry** ppoGeom);
diff --git a/port/cpl_csv.cpp b/port/cpl_csv.cpp
index 12322e8..5f11873 100644
--- a/port/cpl_csv.cpp
+++ b/port/cpl_csv.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_csv.cpp 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: cpl_csv.cpp 29238 2015-05-24 08:42:03Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  CSV (comma separated value) file access.
@@ -33,7 +33,7 @@
 #include "cpl_multiproc.h"
 #include "gdal_csv.h"
 
-CPL_CVSID("$Id: cpl_csv.cpp 28039 2014-11-30 18:24:59Z rouault $");
+CPL_CVSID("$Id: cpl_csv.cpp 29238 2015-05-24 08:42:03Z rouault $");
 
 /* ==================================================================== */
 /*      The CSVTable is a persistant set of info about an open CSV      */
@@ -445,15 +445,16 @@ static void CSVIngest( const char *pszFilename )
 
 /** Detect which field separator is used.
  *
- * Currently, it can detect comma, semicolon or tabulation. In case of
+ * Currently, it can detect comma, semicolon, space or tabulation. In case of
  * ambiguity or no separator found, comma will be considered as the separator.
  *
- * @return ',', ';' or '\t'
+ * @return ',', ';', ' ' or '\t'
  */
 char CSVDetectSeperator (const char* pszLine)
 {
     int     bInString = FALSE;
     char    chDelimiter = '\0';
+    int     nCountSpace = 0;
 
     for( ; *pszLine != '\0'; pszLine++ )
     {
@@ -470,6 +471,8 @@ char CSVDetectSeperator (const char* pszLine)
                 break;
             }
         }
+        else if( !bInString && *pszLine == ' ' )
+            nCountSpace ++;
         else if( *pszLine == '"' )
         {
             if( !bInString || pszLine[1] != '"' )
@@ -485,7 +488,12 @@ char CSVDetectSeperator (const char* pszLine)
     }
 
     if (chDelimiter == '\0')
-        chDelimiter = ',';
+    {
+        if( nCountSpace > 0 )
+            chDelimiter = ' ';
+        else
+            chDelimiter = ',';
+    }
 
     return chDelimiter;
 }
diff --git a/swig/csharp/gdal/Gdal.cs b/swig/csharp/gdal/Gdal.cs
index 83e9af6..9a497a5 100644
--- a/swig/csharp/gdal/Gdal.cs
+++ b/swig/csharp/gdal/Gdal.cs
@@ -302,9 +302,10 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
       return ret;
 }
 
-  public static void VSIFCloseL(IntPtr arg0) {
-    GdalPINVOKE.VSIFCloseL(arg0);
+  public static int VSIFCloseL(IntPtr arg0) {
+    int ret = GdalPINVOKE.VSIFCloseL(arg0);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
   }
 
   public static int VSIFSeekL(IntPtr arg0, int arg1, int arg2) {
diff --git a/swig/csharp/gdal/GdalPINVOKE.cs b/swig/csharp/gdal/GdalPINVOKE.cs
index 67882f4..f83a6ad 100644
--- a/swig/csharp/gdal/GdalPINVOKE.cs
+++ b/swig/csharp/gdal/GdalPINVOKE.cs
@@ -314,7 +314,7 @@ class GdalPINVOKE {
   public static extern IntPtr VSIFOpenL(byte[] jarg1, string jarg2);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFCloseL")]
-  public static extern void VSIFCloseL(IntPtr jarg1);
+  public static extern int VSIFCloseL(IntPtr jarg1);
 
   [DllImport("gdal_wrap", EntryPoint="CSharp_VSIFSeekL")]
   public static extern int VSIFSeekL(IntPtr jarg1, int jarg2, int jarg3);
diff --git a/swig/csharp/gdal/gdal_wrap.cpp b/swig/csharp/gdal/gdal_wrap.cpp
index 4db25fc..c85bd59 100644
--- a/swig/csharp/gdal/gdal_wrap.cpp
+++ b/swig/csharp/gdal/gdal_wrap.cpp
@@ -361,6 +361,8 @@ typedef void GDALAsyncReaderShadow;
 
 /* use this to not return the int returned by GDAL */
 typedef int RETURN_NONE;
+/* return value that is used for VSI methods that return -1 on error (and set errno) */
+typedef int VSI_RETVAL;
 
 
 
@@ -2640,7 +2642,7 @@ SWIGEXPORT void SWIGSTDCALL CSharp_FileFromMemBuffer(char * jarg1, int jarg2, vo
 SWIGEXPORT int SWIGSTDCALL CSharp_Unlink(char * jarg1) {
   int jresult ;
   char *arg1 = (char *) 0 ;
-  int result;
+  VSI_RETVAL result;
   
   arg1 = (char *)jarg1; 
   {
@@ -2652,7 +2654,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Unlink(char * jarg1) {
   }
   {
     CPLErrorReset();
-    result = (int)VSIUnlink((char const *)arg1);
+    result = VSIUnlink((char const *)arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2712,7 +2714,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Mkdir(char * jarg1, int jarg2) {
   int jresult ;
   char *arg1 = (char *) 0 ;
   int arg2 ;
-  int result;
+  VSI_RETVAL result;
   
   arg1 = (char *)jarg1; 
   arg2 = (int)jarg2; 
@@ -2725,7 +2727,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Mkdir(char * jarg1, int jarg2) {
   }
   {
     CPLErrorReset();
-    result = (int)VSIMkdir((char const *)arg1,arg2);
+    result = VSIMkdir((char const *)arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2753,7 +2755,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Mkdir(char * jarg1, int jarg2) {
 SWIGEXPORT int SWIGSTDCALL CSharp_Rmdir(char * jarg1) {
   int jresult ;
   char *arg1 = (char *) 0 ;
-  int result;
+  VSI_RETVAL result;
   
   arg1 = (char *)jarg1; 
   {
@@ -2765,7 +2767,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Rmdir(char * jarg1) {
   }
   {
     CPLErrorReset();
-    result = (int)VSIRmdir((char const *)arg1);
+    result = VSIRmdir((char const *)arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2794,13 +2796,13 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Rename(char * jarg1, char * jarg2) {
   int jresult ;
   char *arg1 = (char *) 0 ;
   char *arg2 = (char *) 0 ;
-  int result;
+  VSI_RETVAL result;
   
   arg1 = (char *)jarg1; 
   arg2 = (char *)jarg2; 
   {
     CPLErrorReset();
-    result = (int)VSIRename((char const *)arg1,(char const *)arg2);
+    result = VSIRename((char const *)arg1,(char const *)arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2867,13 +2869,15 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_VSIFOpenL(char * jarg1, char * jarg2) {
 }
 
 
-SWIGEXPORT void SWIGSTDCALL CSharp_VSIFCloseL(void * jarg1) {
+SWIGEXPORT int SWIGSTDCALL CSharp_VSIFCloseL(void * jarg1) {
+  int jresult ;
   VSILFILE *arg1 = (VSILFILE *) 0 ;
+  VSI_RETVAL result;
   
   arg1 = (VSILFILE *)jarg1; 
   {
     CPLErrorReset();
-    VSIFCloseL(arg1);
+    result = VSIFCloseL(arg1);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2893,6 +2897,8 @@ SWIGEXPORT void SWIGSTDCALL CSharp_VSIFCloseL(void * jarg1) {
     
     
   }
+  jresult = result; 
+  return jresult;
 }
 
 
@@ -2901,14 +2907,14 @@ SWIGEXPORT int SWIGSTDCALL CSharp_VSIFSeekL(void * jarg1, long jarg2, int jarg3)
   VSILFILE *arg1 = (VSILFILE *) 0 ;
   long arg2 ;
   int arg3 ;
-  int result;
+  VSI_RETVAL result;
   
   arg1 = (VSILFILE *)jarg1; 
   arg2 = (long)jarg2; 
   arg3 = (int)jarg3; 
   {
     CPLErrorReset();
-    result = (int)VSIFSeekL(arg1,arg2,arg3);
+    result = VSIFSeekL(arg1,arg2,arg3);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
@@ -2970,13 +2976,13 @@ SWIGEXPORT int SWIGSTDCALL CSharp_VSIFTruncateL(void * jarg1, long jarg2) {
   int jresult ;
   VSILFILE *arg1 = (VSILFILE *) 0 ;
   long arg2 ;
-  int result;
+  VSI_RETVAL result;
   
   arg1 = (VSILFILE *)jarg1; 
   arg2 = (long)jarg2; 
   {
     CPLErrorReset();
-    result = (int)VSIFTruncateL(arg1,arg2);
+    result = VSIFTruncateL(arg1,arg2);
     CPLErr eclass = CPLGetLastErrorType();
     if ( eclass == CE_Failure || eclass == CE_Fatal ) {
       SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
diff --git a/swig/include/Band.i b/swig/include/Band.i
index b3fd717..b1efd0d 100644
--- a/swig/include/Band.i
+++ b/swig/include/Band.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: Band.i 28899 2015-04-14 09:27:00Z rouault $
+ * $Id: Band.i 29216 2015-05-20 15:11:18Z ajolma $
  *
  * Name:     Band.i
  * Project:  GDAL Python Interface
@@ -474,7 +474,11 @@ public:
       return GDALCreateMaskBand( self, nFlags );
   }
 
-#if defined(SWIGPYTHON)
+#if defined(SWIGPYTHON) || defined(SWIGPERL)
+#if defined(SWIGPERL)
+%apply (int len, GUIntBig *output) {(int buckets, GUIntBig *panHistogram)};
+%apply (IF_ERROR_RETURN_NONE) { (CPLErr) }; 
+#endif
 %feature( "kwargs" ) GetHistogram;
   CPLErr GetHistogram( double min=-0.5,
                      double max=255.5,
@@ -490,13 +494,14 @@ public:
                                          callback, callback_data );
     return err;
   }
+#if defined(SWIGPERL)
+%clear (int buckets, int *panHistogram);
+%clear (CPLErr);
+#endif
 #else
 #ifndef SWIGJAVA
 #if defined(SWIGCSHARP)
 %apply (int inout[ANY]) {int *panHistogram};
-#elif defined(SWIGPERL)
-%apply (int len, int *output) {(int buckets, int *panHistogram)};
-%apply (IF_ERROR_RETURN_NONE) { (CPLErr) }; 
 #endif
 %feature( "kwargs" ) GetHistogram;
   CPLErr GetHistogram( double min=-0.5,
@@ -515,14 +520,16 @@ public:
   }
 #if defined(SWIGCSHARP)
 %clear int *panHistogram;
-#elif defined(SWIGPERL)
-%clear (int buckets, int *panHistogram);
-%clear (CPLErr);
 #endif
 #endif
 #endif
 
-#if defined(SWIGPYTHON)
+#if defined(SWIGPYTHON) || defined(SWIGPERL)
+#if defined(SWIGPERL)
+%apply (double *OUTPUT){double *min_ret, double *max_ret}
+%apply (int *nLen, const GUIntBig **pList) {(int *buckets_ret, GUIntBig **ppanHistogram)};
+%apply (IF_ERROR_RETURN_NONE) { (CPLErr) }; 
+#endif
 %feature ("kwargs") GetDefaultHistogram;
 CPLErr GetDefaultHistogram( double *min_ret=NULL, double *max_ret=NULL, int *buckets_ret = NULL, 
                             GUIntBig **ppanHistogram = NULL, int force = 1, 
@@ -532,13 +539,13 @@ CPLErr GetDefaultHistogram( double *min_ret=NULL, double *max_ret=NULL, int *buc
                                     ppanHistogram, force, 
                                     callback, callback_data );
 }
-#else
-#ifndef SWIGJAVA
 #if defined(SWIGPERL)
-%apply (double *OUTPUT){double *min_ret, double *max_ret}
-%apply (int *nLen, const int **pList) {(int *buckets_ret, int **ppanHistogram)};
-%apply (IF_ERROR_RETURN_NONE) { (CPLErr) }; 
+%clear (double *min_ret, double *max_ret);
+%clear (int *buckets_ret, int **ppanHistogram);
+%clear (CPLErr);
 #endif
+#else
+#ifndef SWIGJAVA
 %feature ("kwargs") GetDefaultHistogram;
 CPLErr GetDefaultHistogram( double *min_ret=NULL, double *max_ret=NULL, int *buckets_ret = NULL, 
                             int **ppanHistogram = NULL, int force = 1, 
@@ -548,24 +555,19 @@ CPLErr GetDefaultHistogram( double *min_ret=NULL, double *max_ret=NULL, int *buc
                                     ppanHistogram, force, 
                                     callback, callback_data );
 }
-#if defined(SWIGPERL)
-%clear (double *min_ret, double *max_ret);
-%clear (int *buckets_ret, int **ppanHistogram);
-%clear (CPLErr);
-#endif
 #endif
 #endif
 
-#if defined(SWIGPYTHON)
+#if defined(SWIGPYTHON) || defined(SWIGPERL)
 %apply (int nList, GUIntBig* pList) {(int buckets_in, GUIntBig *panHistogram_in)}
 CPLErr SetDefaultHistogram( double min, double max, 
                             int buckets_in, GUIntBig *panHistogram_in ) {
     return GDALSetDefaultHistogramEx( self, min, max, 
                                     buckets_in, panHistogram_in );
 }
-%clear (int buckets_in, int *panHistogram_in);
+%clear (int buckets_in, GUIntBig *panHistogram_in);
 #else
-#if defined(SWIGPERL) || defined(SWIGJAVA)
+#if defined(SWIGJAVA)
 %apply (int nList, int* pList) {(int buckets_in, int *panHistogram_in)}
 #endif
 CPLErr SetDefaultHistogram( double min, double max, 
@@ -573,7 +575,7 @@ CPLErr SetDefaultHistogram( double min, double max,
     return GDALSetDefaultHistogram( self, min, max, 
     	   			    buckets_in, panHistogram_in );
 }
-#if defined(SWIGPERL) || defined(SWIGJAVA)
+#if defined(SWIGJAVA)
 %clear (int buckets_in, int *panHistogram_in);
 #endif
 #endif
diff --git a/swig/include/cpl.i b/swig/include/cpl.i
index 5be6918..ce2e05c 100644
--- a/swig/include/cpl.i
+++ b/swig/include/cpl.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl.i 28730 2015-03-14 14:24:15Z ajolma $
+ * $Id: cpl.i 29223 2015-05-21 15:19:08Z ajolma $
  *
  * Name:     cpl.i
  * Project:  GDAL Python Interface
@@ -359,7 +359,7 @@ void wrapper_VSIFileFromMemBuffer( const char* utf8_path, int nBytes, const GByt
 #endif
 
 /* Added in GDAL 1.7.0 */
-int VSIUnlink(const char * utf8_path );
+VSI_RETVAL VSIUnlink(const char * utf8_path );
 
 /* Added in GDAL 1.7.0 */
 /* Thread support is necessary for binding languages with threaded GC */
@@ -372,9 +372,9 @@ int wrapper_HasThreadSupport()
 }
 
 /* Added for GDAL 1.8 */
-int VSIMkdir(const char *utf8_path, int mode );
-int VSIRmdir(const char *utf8_path );
-int VSIRename(const char * pszOld, const char *pszNew );
+VSI_RETVAL VSIMkdir(const char *utf8_path, int mode );
+VSI_RETVAL VSIRmdir(const char *utf8_path );
+VSI_RETVAL VSIRename(const char * pszOld, const char *pszNew );
 
 /* Added for GDAL 1.8 
 
@@ -390,9 +390,7 @@ typedef void VSILFILE;
 #endif
 
 #if defined(SWIGPERL)
-%apply RETURN_NONE_TRUE_IS_ERROR {RETURN_NONE};
-RETURN_NONE VSIStatL( const char * utf8_path, VSIStatBufL *psStatBuf );
-%clear RETURN_NONE;
+VSI_RETVAL VSIStatL( const char * utf8_path, VSIStatBufL *psStatBuf );
 
 #elif defined(SWIGPYTHON)
 
@@ -464,16 +462,16 @@ VSILFILE   *wrapper_VSIFOpenL( const char *utf8_path, const char *pszMode )
     return VSIFOpenL( utf8_path, pszMode );
 }
 %}
-void    VSIFCloseL( VSILFILE * );
+VSI_RETVAL VSIFCloseL( VSILFILE * );
 
 #if defined(SWIGPYTHON)
 int     VSIFSeekL( VSILFILE *, GIntBig, int );
 GIntBig    VSIFTellL( VSILFILE * );
 int     VSIFTruncateL( VSILFILE *, GIntBig );
 #else
-int     VSIFSeekL( VSILFILE *, long, int );
+VSI_RETVAL VSIFSeekL( VSILFILE *, long, int );
 long    VSIFTellL( VSILFILE * );
-int     VSIFTruncateL( VSILFILE *, long );
+VSI_RETVAL VSIFTruncateL( VSILFILE *, long );
 #endif
 
 #if defined(SWIGPYTHON)
diff --git a/swig/include/csharp/typemaps_csharp.i b/swig/include/csharp/typemaps_csharp.i
index ed1bb60..bb77316 100644
--- a/swig/include/csharp/typemaps_csharp.i
+++ b/swig/include/csharp/typemaps_csharp.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_csharp.i 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: typemaps_csharp.i 29225 2015-05-21 16:28:00Z rouault $
  *
  * Name:     typemaps_csharp.i
  * Project:  GDAL CSharp Interface
@@ -33,6 +33,8 @@
 
 /* CSHARP TYPEMAPS */
 
+%apply (int) {VSI_RETVAL};
+
 %fragment("OGRErrMessages","header") %{
 static char const *
 OGRErrMessages( int rc ) {
diff --git a/swig/include/gdal.i b/swig/include/gdal.i
index f152e9d..4064ed1 100644
--- a/swig/include/gdal.i
+++ b/swig/include/gdal.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal.i 28713 2015-03-10 20:19:21Z ajolma $
+ * $Id: gdal.i 29227 2015-05-21 16:58:30Z ajolma $
  *
  * Name:     gdal.i
  * Project:  GDAL Python Interface
@@ -96,6 +96,8 @@ typedef int OGRErr;
 %{
 /* use this to not return the int returned by GDAL */
 typedef int RETURN_NONE;
+/* return value that is used for VSI methods that return -1 on error (and set errno) */
+typedef int VSI_RETVAL;
 
 %}
 
diff --git a/swig/include/java/typemaps_java.i b/swig/include/java/typemaps_java.i
index b9776c2..1c3415f 100644
--- a/swig/include/java/typemaps_java.i
+++ b/swig/include/java/typemaps_java.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_java.i 26068 2013-06-06 20:46:21Z rouault $
+ * $Id: typemaps_java.i 29225 2015-05-21 16:28:00Z rouault $
  *
  * Name:     typemaps_java.i
  * Project:  GDAL SWIG Interface
@@ -20,6 +20,8 @@
 %include "arrays_java.i";
 %include "typemaps.i"
 
+%apply (int) {VSI_RETVAL};
+
 %typemap(javabody) SWIGTYPE %{
   private long swigCPtr;
   protected boolean swigCMemOwn;
diff --git a/swig/include/perl/gdal_perl.i b/swig/include/perl/gdal_perl.i
index aef7cf6..d4a9c17 100644
--- a/swig/include/perl/gdal_perl.i
+++ b/swig/include/perl/gdal_perl.i
@@ -1369,7 +1369,12 @@ sub Write {
 
 sub Close {
     my ($self, $data) = @_;
-    Geo::GDAL::VSIFCloseL($self);
+    eval {
+        Geo::GDAL::VSIFCloseL($self);
+    };
+    if ($@) {
+        confess "Cannot close file: $@.";
+    }
 }
 
 sub Read {
@@ -1389,14 +1394,25 @@ sub Tell {
 
 sub Truncate {
     my ($self, $new_size) = @_;
-    Geo::GDAL::VSIFTruncateL($self, $new_size);
+    eval {
+        Geo::GDAL::VSIFTruncateL($self, $new_size);
+    };
+    if ($@) {
+        confess "Cannot truncate file: $@.";
+    }
 }
 
-sub Mkdir {
-    my ($path, $mode) = @_;
-    Geo::GDAL::Mkdir($path, $mode);
+sub MkDir {
+    my ($path) = @_;
+    my $mode = 0; # unused in CPL
+    eval {
+        Geo::GDAL::Mkdir($path, $mode);
+    };
+    if ($@) {
+        confess "Cannot make directory \"$path\": $@.";
+    }
 }
-*MkDir = *Mkdir;
+*Mkdir = *MkDir;
 
 sub ReadDir {
     my ($path) = @_;
@@ -1410,37 +1426,58 @@ sub ReadDirRecursive {
 
 sub Rename {
     my ($old, $new) = @_;
-    Geo::GDAL::Rename($old, $new);
+    eval {
+        Geo::GDAL::Rename($old, $new);
+    };
+    if ($@) {
+        confess "Cannot rename file \"$old\": $@.";
+    }
 }
 
-sub Rmdir {
+sub RmDir {
     my ($dirname, $recursive) = @_;
-    if (!$recursive) {
-        Geo::GDAL::Rmdir($dirname);
-    } else {
-        for my $f (ReadDir($dirname)) {
-            next if $f eq '..' or $f eq '.';
-            my @s = Stat($dirname.'/'.$f);
-            if ($s[0] eq 'f') {
-                Unlink($dirname.'/'.$f);
-            } elsif ($s[0] eq 'd') {
-                Rmdir($dirname.'/'.$f, 1);
-                Rmdir($dirname.'/'.$f);
+    eval {
+        if (!$recursive) {
+            Geo::GDAL::Rmdir($dirname);
+        } else {
+            for my $f (ReadDir($dirname)) {
+                next if $f eq '..' or $f eq '.';
+                my @s = Stat($dirname.'/'.$f);
+                if ($s[0] eq 'f') {
+                    Unlink($dirname.'/'.$f);
+                } elsif ($s[0] eq 'd') {
+                    Rmdir($dirname.'/'.$f, 1);
+                    Rmdir($dirname.'/'.$f);
+                }
             }
+            RmDir($dirname);
         }
-        Rmdir($dirname);
+    };
+    if ($@) {
+        my $r = $recursive ? ' recursively' : '';
+        confess "Cannot remove directory \"$dirname\"$r: $@.";
     }
 }
-*RmDir = *Rmdir;
+*Rmdir = *RmDir;
 
 sub Stat {
     my ($path) = @_;
-    Geo::GDAL::Stat($path);
+    eval {
+        Geo::GDAL::Stat($path);
+    };
+    if ($@) {
+        confess "Cannot stat file \"$path\": $@.";
+    }
 }
 
 sub Unlink {
     my ($filename) = @_;
-    Geo::GDAL::Unlink($filename);
+    eval {
+        Geo::GDAL::Unlink($filename);
+    };
+    if ($@) {
+        confess "Cannot unlink file \"$filename\": $@.";
+    }
 }
 
 
diff --git a/swig/include/perl/typemaps_perl.i b/swig/include/perl/typemaps_perl.i
index c58cbfe..6e7c520 100644
--- a/swig/include/perl/typemaps_perl.i
+++ b/swig/include/perl/typemaps_perl.i
@@ -133,6 +133,25 @@
   sv_2mortal($result);
   argvi++;
 }
+
+/* typemaps for VSI_RETVAL */
+
+/* drop GDAL return value */
+%typemap(out) VSI_RETVAL
+{
+  /* %typemap(out) VSI_RETVAL */
+}
+/* croak if GDAL returns -1 */
+%typemap(ret) VSI_RETVAL
+{
+ /* %typemap(ret) VSI_RETVAL */
+  if ($1 == -1 ) {
+    croak(strerror(errno));
+  }
+}
+
+/* typemaps for IF_FALSE_RETURN_NONE */
+
 /* drop GDAL return value */
 %typemap(out) IF_FALSE_RETURN_NONE
 {
@@ -224,6 +243,21 @@ CreateArrayFromIntArray( int *first, unsigned int size ) {
 }
 %}
 
+%fragment("CreateArrayFromGUIntBigArray","header") %{
+#define LENGTH_OF_GUIntBig_AS_STRING 30
+static SV *
+CreateArrayFromGUIntBigArray( GUIntBig *first, unsigned int size ) {
+  AV *av = (AV*)sv_2mortal((SV*)newAV());
+  for( unsigned int i=0; i<size; i++ ) {
+    char s[LENGTH_OF_GUIntBig_AS_STRING];
+    snprintf(s, LENGTH_OF_GUIntBig_AS_STRING-1, CPL_FRMT_GUIB, *first);
+    av_store(av,i,newSVpv(s, 0));
+    ++first;
+  }
+  return sv_2mortal(newRV((SV*)av));
+}
+%}
+
 %fragment("CreateArrayFromDoubleArray","header") %{
 static SV *
 CreateArrayFromDoubleArray( double *first, unsigned int size ) {
@@ -250,6 +284,8 @@ CreateArrayFromStringArray( char **first ) {
 }
 %}
 
+/* typemaps for (int *nLen, const int **pList) */
+
 %typemap(in,numinputs=0) (int *nLen, const int **pList) (int nLen, int *pList)
 {
   /* %typemap(in,numinputs=0) (int *nLen, const int **pList) */
@@ -263,6 +299,23 @@ CreateArrayFromStringArray( char **first ) {
   argvi++;
 }
 
+/* typemaps for (int *nLen, const GUIntBig **pList) */
+
+%typemap(in,numinputs=0) (int *nLen, const GUIntBig **pList) (int nLen, GUIntBig *pList)
+{
+  /* %typemap(in,numinputs=0) (int *nLen, const GUIntBig **pList) */
+  $1 = &nLen;
+  $2 = &pList;
+}
+%typemap(argout,fragment="CreateArrayFromGUIntBigArray") (int *nLen, const GUIntBig **pList)
+{
+  /* %typemap(argout) (int *nLen, const GUIntBig **pList) */
+  $result = CreateArrayFromGUIntBigArray( *($2), *($1) );
+  argvi++;
+}
+
+/* typemaps for (int len, int *output) */
+
 %typemap(in,numinputs=1) (int len, int *output)
 {
   /* %typemap(in,numinputs=1) (int len, int *output) */
@@ -283,7 +336,7 @@ CreateArrayFromStringArray( char **first ) {
     int i;
     EXTEND(SP, argvi+$1-items+1);
     for (i = 0; i < $1; i++)
-      ST(argvi++) = sv_2mortal(newSVnv($2[i]));
+      ST(argvi++) = sv_2mortal(newSViv($2[i]));
   } else {
     $result = CreateArrayFromIntArray( $2, $1 );
     argvi++;
@@ -295,6 +348,45 @@ CreateArrayFromStringArray( char **first ) {
   CPLFree($2);
 }
 
+/* typemaps for (int len, GUIntBig *output) */
+
+%typemap(in,numinputs=1) (int len, GUIntBig *output)
+{
+  /* %typemap(in,numinputs=1) (int len, GUIntBig *output) */
+  $1 = SvIV($input);
+}
+%typemap(check) (int len, GUIntBig *output)
+{
+  /* %typemap(check) (int len, GUIntBig *output) */
+  if ($1 < 1) $1 = 1; /* stop idiocy */
+  $2 = (GUIntBig*)CPLMalloc( $1 * sizeof(GUIntBig) );
+    
+}
+%typemap(argout,fragment="CreateArrayFromGUIntBigArray") (int len, GUIntBig *output)
+{
+  /* %typemap(argout) (int len, GUIntBig *output) */
+  if (GIMME_V == G_ARRAY) {
+    /* return a list */
+    int i;
+    EXTEND(SP, argvi+$1-items+1);
+    for (i = 0; i < $1; i++) {
+      char s[LENGTH_OF_GUIntBig_AS_STRING];
+      snprintf(s, LENGTH_OF_GUIntBig_AS_STRING-1, CPL_FRMT_GUIB, $2[i]);
+      ST(argvi++) = sv_2mortal(newSVpv(s, 0));
+    }
+  } else {
+    $result = CreateArrayFromGUIntBigArray( $2, $1 );
+    argvi++;
+  }
+}
+%typemap(freearg) (int len, GUIntBig *output)
+{
+  /* %typemap(freearg) (int len, GUIntBig *output) */
+  CPLFree($2);
+}
+
+/* typemaps for (int nLen, double *pList) */
+
 %typemap(in,numinputs=0) (int *nLen, const double **pList) (int nLen, double *pList)
 {
   /* %typemap(in,numinputs=0) (int *nLen, const double **pList) */
@@ -369,9 +461,8 @@ CreateArrayFromStringArray( char **first ) {
     }
 }
 
-/*
- *  Typemap for counted arrays of ints <- Perl list
- */
+/* typemaps for (int nList, int* pList) */
+
 %typemap(in,numinputs=1) (int nList, int* pList)
 {
     /* %typemap(in,numinputs=1) (int nList, int* pList) */
@@ -394,6 +485,32 @@ CreateArrayFromStringArray( char **first ) {
     CPLFree((void*) $2);
 }
 
+/* typemaps for (int nList, GUIntBig* pList) */
+
+%typemap(in,numinputs=1) (int nList, GUIntBig* pList)
+{
+    /* %typemap(in,numinputs=1) (int nList, GUIntBig* pList) */
+    if (!(SvROK($input) && (SvTYPE(SvRV($input))==SVt_PVAV)))
+        SWIG_croak("Expected a reference to an array.");
+    AV *av = (AV*)(SvRV($input));
+    $1 = av_len(av)+1;
+    $2 = (GUIntBig*)CPLMalloc($1*sizeof(GUIntBig));
+    if ($2) {
+        for( int i = 0; i<$1; i++ ) {
+            SV **sv = av_fetch(av, i, 0);
+            $2[i] =  strtoull(SvPV_nolen(*sv), NULL, 10);
+        }
+    } else
+        SWIG_fail;
+}
+%typemap(freearg) (int nList, GUIntBig* pList)
+{
+    /* %typemap(freearg) (int nList, GUIntBig* pList) */
+    CPLFree((void*) $2);
+}
+
+/* typemaps for (int nList, double* pList) */
+
 %typemap(in,numinputs=1) (int nList, double* pList)
 {
     /* %typemap(in,numinputs=1) (int nList, double* pList) */
diff --git a/swig/include/python/typemaps_python.i b/swig/include/python/typemaps_python.i
index 8a916d6..2d9366b 100644
--- a/swig/include/python/typemaps_python.i
+++ b/swig/include/python/typemaps_python.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_python.i 28899 2015-04-14 09:27:00Z rouault $
+ * $Id: typemaps_python.i 29225 2015-05-21 16:28:00Z rouault $
  *
  * Name:     typemaps_python.i
  * Project:  GDAL Python Interface
@@ -22,6 +22,8 @@
  */
 %include "typemaps.i"
 
+%apply (int) {VSI_RETVAL};
+
 %apply (double *OUTPUT) { double *argout };
 
 %typemap(in) GIntBig
diff --git a/swig/perl/cr.dox b/swig/perl/cr.dox
index f5ed01f..cc5284e 100644
--- a/swig/perl/cr.dox
+++ b/swig/perl/cr.dox
@@ -31,7 +31,7 @@ $nodata = -1;         # nodata value
 $dataset = Geo::GDAL::Driver($driver)->Create($name.$ext, $width, $height, $bands, $datatype);
 # Set the transformation matrix from pixels to projection, note minus in front of $dy
 $dataset->GeoTransform($minx, $dx, 0, $maxy, 0, -$dy);
-$dataset->Projection(Geo::OSR::SpatialReference->create(EPSG=>$epsg)->As('WKT'));
+$dataset->Projection(Geo::OSR::SpatialReference->new(EPSG=>$epsg)->As('WKT'));
 $band = $dataset->Band(1);
 $band->NoDataValue($nodata);
 
diff --git a/swig/perl/cv.dox b/swig/perl/cv.dox
index fa67c55..a6a7517 100644
--- a/swig/perl/cv.dox
+++ b/swig/perl/cv.dox
@@ -31,7 +31,7 @@ eval {
 };
 die "Can't create data source $dsname: $@" if $@;
 
-$osr = Geo::OSR::SpatialReference->create(WGS => 84);
+$osr = Geo::OSR::SpatialReference->new(WGS => 84);
 
 $layer = $datasource->CreateLayer(
     Name => $lname, 
diff --git a/swig/perl/gdal_wrap.cpp b/swig/perl/gdal_wrap.cpp
index d77ba65..36250f1 100644
--- a/swig/perl/gdal_wrap.cpp
+++ b/swig/perl/gdal_wrap.cpp
@@ -1526,19 +1526,20 @@ SWIG_Perl_SetModule(swig_module_info *module) {
 #define SWIGTYPE_p_GDALRasterBandShadow swig_types[11]
 #define SWIGTYPE_p_GDALTransformerInfoShadow swig_types[12]
 #define SWIGTYPE_p_GDAL_GCP swig_types[13]
-#define SWIGTYPE_p_OGRLayerShadow swig_types[14]
-#define SWIGTYPE_p_VSIStatBufL swig_types[15]
-#define SWIGTYPE_p_char swig_types[16]
-#define SWIGTYPE_p_double swig_types[17]
-#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[18]
-#define SWIGTYPE_p_int swig_types[19]
-#define SWIGTYPE_p_p_GDALRasterBandShadow swig_types[20]
-#define SWIGTYPE_p_p_GDAL_GCP swig_types[21]
-#define SWIGTYPE_p_p_char swig_types[22]
-#define SWIGTYPE_p_p_int swig_types[23]
-#define SWIGTYPE_p_void swig_types[24]
-static swig_type_info *swig_types[26];
-static swig_module_info swig_module = {swig_types, 25, 0, 0, 0, 0};
+#define SWIGTYPE_p_GUIntBig swig_types[14]
+#define SWIGTYPE_p_OGRLayerShadow swig_types[15]
+#define SWIGTYPE_p_VSIStatBufL swig_types[16]
+#define SWIGTYPE_p_char swig_types[17]
+#define SWIGTYPE_p_double swig_types[18]
+#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[19]
+#define SWIGTYPE_p_int swig_types[20]
+#define SWIGTYPE_p_p_GDALRasterBandShadow swig_types[21]
+#define SWIGTYPE_p_p_GDAL_GCP swig_types[22]
+#define SWIGTYPE_p_p_GUIntBig swig_types[23]
+#define SWIGTYPE_p_p_char swig_types[24]
+#define SWIGTYPE_p_void swig_types[25]
+static swig_type_info *swig_types[27];
+static swig_module_info swig_module = {swig_types, 26, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -1599,6 +1600,8 @@ typedef void GDALAsyncReaderShadow;
 
 /* use this to not return the int returned by GDAL */
 typedef int RETURN_NONE;
+/* return value that is used for VSI methods that return -1 on error (and set errno) */
+typedef int VSI_RETVAL;
 
 
 
@@ -2902,31 +2905,34 @@ SWIGINTERN CPLErr GDALRasterBandShadow_CreateMaskBand(GDALRasterBandShadow *self
       return GDALCreateMaskBand( self, nFlags );
   }
 
+#define LENGTH_OF_GUIntBig_AS_STRING 30
 static SV *
-CreateArrayFromIntArray( int *first, unsigned int size ) {
+CreateArrayFromGUIntBigArray( GUIntBig *first, unsigned int size ) {
   AV *av = (AV*)sv_2mortal((SV*)newAV());
   for( unsigned int i=0; i<size; i++ ) {
-    av_store(av,i,newSViv(*first));
+    char s[LENGTH_OF_GUIntBig_AS_STRING];
+    snprintf(s, LENGTH_OF_GUIntBig_AS_STRING-1, CPL_FRMT_GUIB, *first);
+    av_store(av,i,newSVpv(s, 0));
     ++first;
   }
   return sv_2mortal(newRV((SV*)av));
 }
 
-SWIGINTERN CPLErr GDALRasterBandShadow_GetHistogram(GDALRasterBandShadow *self,double min=-0.5,double max=255.5,int buckets=256,int *panHistogram=NULL,int include_out_of_range=0,int approx_ok=1,GDALProgressFunc callback=NULL,void *callback_data=NULL){
+SWIGINTERN CPLErr GDALRasterBandShadow_GetHistogram(GDALRasterBandShadow *self,double min=-0.5,double max=255.5,int buckets=256,GUIntBig *panHistogram=NULL,int include_out_of_range=0,int approx_ok=1,GDALProgressFunc callback=NULL,void *callback_data=NULL){
     CPLErrorReset(); 
-    CPLErr err = GDALGetRasterHistogram( self, min, max, buckets, panHistogram,
+    CPLErr err = GDALGetRasterHistogramEx( self, min, max, buckets, panHistogram,
                                          include_out_of_range, approx_ok,
                                          callback, callback_data );
     return err;
   }
-SWIGINTERN CPLErr GDALRasterBandShadow_GetDefaultHistogram(GDALRasterBandShadow *self,double *min_ret=NULL,double *max_ret=NULL,int *buckets_ret=NULL,int **ppanHistogram=NULL,int force=1,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    return GDALGetDefaultHistogram( self, min_ret, max_ret, buckets_ret,
+SWIGINTERN CPLErr GDALRasterBandShadow_GetDefaultHistogram(GDALRasterBandShadow *self,double *min_ret=NULL,double *max_ret=NULL,int *buckets_ret=NULL,GUIntBig **ppanHistogram=NULL,int force=1,GDALProgressFunc callback=NULL,void *callback_data=NULL){
+    return GDALGetDefaultHistogramEx( self, min_ret, max_ret, buckets_ret,
                                     ppanHistogram, force, 
                                     callback, callback_data );
 }
-SWIGINTERN CPLErr GDALRasterBandShadow_SetDefaultHistogram(GDALRasterBandShadow *self,double min,double max,int buckets_in,int *panHistogram_in){
-    return GDALSetDefaultHistogram( self, min, max, 
-    	   			    buckets_in, panHistogram_in );
+SWIGINTERN CPLErr GDALRasterBandShadow_SetDefaultHistogram(GDALRasterBandShadow *self,double min,double max,int buckets_in,GUIntBig *panHistogram_in){
+    return GDALSetDefaultHistogramEx( self, min, max, 
+                                    buckets_in, panHistogram_in );
 }
 SWIGINTERN bool GDALRasterBandShadow_HasArbitraryOverviews(GDALRasterBandShadow *self){
       return (GDALHasArbitraryOverviews( self ) != 0) ? true : false;
@@ -5321,7 +5327,7 @@ XS(_wrap_Unlink) {
   {
     char *arg1 = (char *) 0 ;
     int argvi = 0;
-    int result;
+    VSI_RETVAL result;
     dXSARGS;
     
     {
@@ -5345,7 +5351,7 @@ XS(_wrap_Unlink) {
     }
     {
       CPLErrorReset();
-      result = (int)VSIUnlink((char const *)arg1);
+      result = VSIUnlink((char const *)arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5367,7 +5373,15 @@ XS(_wrap_Unlink) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    {
+      /* %typemap(out) VSI_RETVAL */
+    }
+    {
+      /* %typemap(ret) VSI_RETVAL */
+      if (result == -1 ) {
+        croak(strerror(errno));
+      }
+    }
     XSRETURN(argvi);
   fail:
     SWIG_croak_null();
@@ -5423,7 +5437,7 @@ XS(_wrap_Mkdir) {
     int val2 ;
     int ecode2 = 0 ;
     int argvi = 0;
-    int result;
+    VSI_RETVAL result;
     dXSARGS;
     
     {
@@ -5454,7 +5468,7 @@ XS(_wrap_Mkdir) {
     }
     {
       CPLErrorReset();
-      result = (int)VSIMkdir((char const *)arg1,arg2);
+      result = VSIMkdir((char const *)arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5476,8 +5490,16 @@ XS(_wrap_Mkdir) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    {
+      /* %typemap(out) VSI_RETVAL */
+    }
     
+    {
+      /* %typemap(ret) VSI_RETVAL */
+      if (result == -1 ) {
+        croak(strerror(errno));
+      }
+    }
     XSRETURN(argvi);
   fail:
     
@@ -5490,7 +5512,7 @@ XS(_wrap_Rmdir) {
   {
     char *arg1 = (char *) 0 ;
     int argvi = 0;
-    int result;
+    VSI_RETVAL result;
     dXSARGS;
     
     {
@@ -5514,7 +5536,7 @@ XS(_wrap_Rmdir) {
     }
     {
       CPLErrorReset();
-      result = (int)VSIRmdir((char const *)arg1);
+      result = VSIRmdir((char const *)arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5536,7 +5558,15 @@ XS(_wrap_Rmdir) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    {
+      /* %typemap(out) VSI_RETVAL */
+    }
+    {
+      /* %typemap(ret) VSI_RETVAL */
+      if (result == -1 ) {
+        croak(strerror(errno));
+      }
+    }
     XSRETURN(argvi);
   fail:
     SWIG_croak_null();
@@ -5555,7 +5585,7 @@ XS(_wrap_Rename) {
     char *buf2 = 0 ;
     int alloc2 = 0 ;
     int argvi = 0;
-    int result;
+    VSI_RETVAL result;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
@@ -5573,7 +5603,7 @@ XS(_wrap_Rename) {
     arg2 = reinterpret_cast< char * >(buf2);
     {
       CPLErrorReset();
-      result = (int)VSIRename((char const *)arg1,(char const *)arg2);
+      result = VSIRename((char const *)arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5595,9 +5625,17 @@ XS(_wrap_Rename) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    {
+      /* %typemap(out) VSI_RETVAL */
+    }
     if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    {
+      /* %typemap(ret) VSI_RETVAL */
+      if (result == -1 ) {
+        croak(strerror(errno));
+      }
+    }
     XSRETURN(argvi);
   fail:
     if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -5613,7 +5651,7 @@ XS(_wrap_Stat) {
     VSIStatBufL *arg2 = (VSIStatBufL *) 0 ;
     VSIStatBufL sStatBuf2 ;
     int argvi = 0;
-    RETURN_NONE result;
+    VSI_RETVAL result;
     dXSARGS;
     
     {
@@ -5664,7 +5702,7 @@ XS(_wrap_Stat) {
       
     }
     {
-      /* %typemap(out) RETURN_NONE_TRUE_IS_ERROR */
+      /* %typemap(out) VSI_RETVAL */
     }
     {
       /* %typemap(argout) (VSIStatBufL *) */
@@ -5688,9 +5726,9 @@ XS(_wrap_Stat) {
     }
     
     {
-      /* %typemap(ret) RETURN_NONE_TRUE_IS_ERROR */
-      if (result != 0 ) {
-        SWIG_croak("unexpected error in 'Stat'");
+      /* %typemap(ret) VSI_RETVAL */
+      if (result == -1 ) {
+        croak(strerror(errno));
       }
     }
     XSRETURN(argvi);
@@ -5777,6 +5815,7 @@ XS(_wrap_VSIFCloseL) {
     VSILFILE *arg1 = (VSILFILE *) 0 ;
     int res1 ;
     int argvi = 0;
+    VSI_RETVAL result;
     dXSARGS;
     
     if ((items < 1) || (items > 1)) {
@@ -5788,7 +5827,7 @@ XS(_wrap_VSIFCloseL) {
     }
     {
       CPLErrorReset();
-      VSIFCloseL(arg1);
+      result = VSIFCloseL(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5811,9 +5850,15 @@ XS(_wrap_VSIFCloseL) {
       
     }
     {
-      /* %typemap(out) void */
+      /* %typemap(out) VSI_RETVAL */
     }
     
+    {
+      /* %typemap(ret) VSI_RETVAL */
+      if (result == -1 ) {
+        croak(strerror(errno));
+      }
+    }
     XSRETURN(argvi);
   fail:
     
@@ -5833,7 +5878,7 @@ XS(_wrap_VSIFSeekL) {
     int val3 ;
     int ecode3 = 0 ;
     int argvi = 0;
-    int result;
+    VSI_RETVAL result;
     dXSARGS;
     
     if ((items < 3) || (items > 3)) {
@@ -5855,7 +5900,7 @@ XS(_wrap_VSIFSeekL) {
     arg3 = static_cast< int >(val3);
     {
       CPLErrorReset();
-      result = (int)VSIFSeekL(arg1,arg2,arg3);
+      result = VSIFSeekL(arg1,arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5877,10 +5922,18 @@ XS(_wrap_VSIFSeekL) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    {
+      /* %typemap(out) VSI_RETVAL */
+    }
     
     
     
+    {
+      /* %typemap(ret) VSI_RETVAL */
+      if (result == -1 ) {
+        croak(strerror(errno));
+      }
+    }
     XSRETURN(argvi);
   fail:
     
@@ -5948,7 +6001,7 @@ XS(_wrap_VSIFTruncateL) {
     long val2 ;
     int ecode2 = 0 ;
     int argvi = 0;
-    int result;
+    VSI_RETVAL result;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
@@ -5965,7 +6018,7 @@ XS(_wrap_VSIFTruncateL) {
     arg2 = static_cast< long >(val2);
     {
       CPLErrorReset();
-      result = (int)VSIFTruncateL(arg1,arg2);
+      result = VSIFTruncateL(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         SWIG_exception_fail( SWIG_RuntimeError, CPLGetLastErrorMsg() );
@@ -5987,9 +6040,17 @@ XS(_wrap_VSIFTruncateL) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    {
+      /* %typemap(out) VSI_RETVAL */
+    }
     
     
+    {
+      /* %typemap(ret) VSI_RETVAL */
+      if (result == -1 ) {
+        croak(strerror(errno));
+      }
+    }
     XSRETURN(argvi);
   fail:
     
@@ -15201,7 +15262,7 @@ XS(_wrap_Band__GetHistogram) {
     double arg2 = (double) -0.5 ;
     double arg3 = (double) 255.5 ;
     int arg4 = (int) 256 ;
-    int *arg5 = (int *) NULL ;
+    GUIntBig *arg5 = (GUIntBig *) NULL ;
     int arg6 = (int) 0 ;
     int arg7 = (int) 1 ;
     GDALProgressFunc arg8 = (GDALProgressFunc) NULL ;
@@ -15250,7 +15311,7 @@ XS(_wrap_Band__GetHistogram) {
     }
     if (items > 3) {
       {
-        /* %typemap(in,numinputs=1) (int len, int *output) */
+        /* %typemap(in,numinputs=1) (int len, GUIntBig *output) */
         arg4 = SvIV(ST(3));
       }
     }
@@ -15293,9 +15354,9 @@ XS(_wrap_Band__GetHistogram) {
       }
     }
     {
-      /* %typemap(check) (int len, int *output) */
+      /* %typemap(check) (int len, GUIntBig *output) */
       if (arg4 < 1) arg4 = 1; /* stop idiocy */
-      arg5 = (int *)CPLMalloc( arg4 * sizeof(int) );
+      arg5 = (GUIntBig*)CPLMalloc( arg4 * sizeof(GUIntBig) );
       
     }
     _saved[0] = ST(3);
@@ -15327,15 +15388,18 @@ XS(_wrap_Band__GetHistogram) {
       /* %typemap(out) IF_ERROR_RETURN_NONE */
     }
     {
-      /* %typemap(argout) (int len, int *output) */
+      /* %typemap(argout) (int len, GUIntBig *output) */
       if (GIMME_V == G_ARRAY) {
         /* return a list */
         int i;
         EXTEND(SP, argvi+arg4-items+1);
-        for (i = 0; i < arg4; i++)
-        ST(argvi++) = sv_2mortal(newSVnv(arg5[i]));
+        for (i = 0; i < arg4; i++) {
+          char s[LENGTH_OF_GUIntBig_AS_STRING];
+          snprintf(s, LENGTH_OF_GUIntBig_AS_STRING-1, CPL_FRMT_GUIB, arg5[i]);
+          ST(argvi++) = sv_2mortal(newSVpv(s, 0));
+        }
       } else {
-        ST(argvi) = CreateArrayFromIntArray( arg5, arg4 );
+        ST(argvi) = CreateArrayFromGUIntBigArray( arg5, arg4 );
         argvi++;
       }
     }
@@ -15343,7 +15407,7 @@ XS(_wrap_Band__GetHistogram) {
     
     
     {
-      /* %typemap(freearg) (int len, int *output) */
+      /* %typemap(freearg) (int len, GUIntBig *output) */
       CPLFree(arg5);
     }
     
@@ -15355,7 +15419,7 @@ XS(_wrap_Band__GetHistogram) {
     
     
     {
-      /* %typemap(freearg) (int len, int *output) */
+      /* %typemap(freearg) (int len, GUIntBig *output) */
       CPLFree(arg5);
     }
     
@@ -15372,7 +15436,7 @@ XS(_wrap_Band_GetDefaultHistogram) {
     double *arg2 = (double *) NULL ;
     double *arg3 = (double *) NULL ;
     int *arg4 = (int *) NULL ;
-    int **arg5 = (int **) NULL ;
+    GUIntBig **arg5 = (GUIntBig **) NULL ;
     int arg6 = (int) 1 ;
     GDALProgressFunc arg7 = (GDALProgressFunc) NULL ;
     void *arg8 = (void *) NULL ;
@@ -15383,7 +15447,7 @@ XS(_wrap_Band_GetDefaultHistogram) {
     double temp3 ;
     int res3 = SWIG_TMPOBJ ;
     int nLen4 ;
-    int *pList4 ;
+    GUIntBig *pList4 ;
     int val6 ;
     int ecode6 = 0 ;
     int argvi = 0;
@@ -15398,7 +15462,7 @@ XS(_wrap_Band_GetDefaultHistogram) {
     arg2 = &temp2;
     arg3 = &temp3;
     {
-      /* %typemap(in,numinputs=0) (int *nLen4, const int **pList4) */
+      /* %typemap(in,numinputs=0) (int *nLen4, const GUIntBig **pList4) */
       arg4 = &nLen4;
       arg5 = &pList4;
     }
@@ -15481,8 +15545,8 @@ XS(_wrap_Band_GetDefaultHistogram) {
       if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_double, new_flags); argvi++  ;
     }
     {
-      /* %typemap(argout) (int *nLen, const int **pList) */
-      ST(argvi) = CreateArrayFromIntArray( *(arg5), *(arg4) );
+      /* %typemap(argout) (int *nLen, const GUIntBig **pList) */
+      ST(argvi) = CreateArrayFromGUIntBigArray( *(arg5), *(arg4) );
       argvi++;
     }
     
@@ -15508,7 +15572,7 @@ XS(_wrap_Band_SetDefaultHistogram) {
     double arg2 ;
     double arg3 ;
     int arg4 ;
-    int *arg5 = (int *) 0 ;
+    GUIntBig *arg5 = (GUIntBig *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     double val2 ;
@@ -15538,16 +15602,16 @@ XS(_wrap_Band_SetDefaultHistogram) {
     } 
     arg3 = static_cast< double >(val3);
     {
-      /* %typemap(in,numinputs=1) (int nList, int* pList) */
+      /* %typemap(in,numinputs=1) (int nList, GUIntBig* pList) */
       if (!(SvROK(ST(3)) && (SvTYPE(SvRV(ST(3)))==SVt_PVAV)))
       SWIG_croak("Expected a reference to an array.");
       AV *av = (AV*)(SvRV(ST(3)));
       arg4 = av_len(av)+1;
-      arg5 = (int*)CPLMalloc(arg4*sizeof(int));
+      arg5 = (GUIntBig*)CPLMalloc(arg4*sizeof(GUIntBig));
       if (arg5) {
         for( int i = 0; i<arg4; i++ ) {
           SV **sv = av_fetch(av, i, 0);
-          arg5[i] =  SvIV(*sv);
+          arg5[i] =  strtoull(SvPV_nolen(*sv), NULL, 10);
         }
       } else
       SWIG_fail;
@@ -15581,7 +15645,7 @@ XS(_wrap_Band_SetDefaultHistogram) {
     
     
     {
-      /* %typemap(freearg) (int nList, int* pList) */
+      /* %typemap(freearg) (int nList, GUIntBig* pList) */
       CPLFree((void*) arg5);
     }
     XSRETURN(argvi);
@@ -15590,7 +15654,7 @@ XS(_wrap_Band_SetDefaultHistogram) {
     
     
     {
-      /* %typemap(freearg) (int nList, int* pList) */
+      /* %typemap(freearg) (int nList, GUIntBig* pList) */
       CPLFree((void*) arg5);
     }
     SWIG_croak_null();
@@ -22775,6 +22839,7 @@ static swig_type_info _swigt__p_GDALRasterAttributeTableShadow = {"_p_GDALRaster
 static swig_type_info _swigt__p_GDALRasterBandShadow = {"_p_GDALRasterBandShadow", "GDALRasterBandShadow *", 0, 0, (void*)"Geo::GDAL::Band", 0};
 static swig_type_info _swigt__p_GDALTransformerInfoShadow = {"_p_GDALTransformerInfoShadow", "GDALTransformerInfoShadow *", 0, 0, (void*)"Geo::GDAL::Transformer", 0};
 static swig_type_info _swigt__p_GDAL_GCP = {"_p_GDAL_GCP", "GDAL_GCP *", 0, 0, (void*)"Geo::GDAL::GCP", 0};
+static swig_type_info _swigt__p_GUIntBig = {"_p_GUIntBig", "GUIntBig *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OGRLayerShadow = {"_p_OGRLayerShadow", "OGRLayerShadow *", 0, 0, (void*)"Geo::OGR::Layer", 0};
 static swig_type_info _swigt__p_VSIStatBufL = {"_p_VSIStatBufL", "VSIStatBufL *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_char = {"_p_char", "char *|retStringAndCPLFree *", 0, 0, (void*)0, 0};
@@ -22783,8 +22848,8 @@ static swig_type_info _swigt__p_f_double_p_q_const__char_p_void__int = {"_p_f_do
 static swig_type_info _swigt__p_int = {"_p_int", "OGRFieldSubType *|GDALRATFieldType *|OGRFieldType *|int *|GDALAccess *|OGRwkbByteOrder *|CPLErr *|GDALRWFlag *|OGRJustification *|GDALRATFieldUsage *|GDALTileOrganization *|GDALPaletteInterp *|GDALColorInterp *|GDALResampleAlg *|GDALRIOResampleAlg *|OGRErr *|OGRwkbGeometryType *|GDALDataType *|GDALAsyncStatusType *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_GDALRasterBandShadow = {"_p_p_GDALRasterBandShadow", "GDALRasterBandShadow **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_GDAL_GCP = {"_p_p_GDAL_GCP", "GDAL_GCP **", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_p_GUIntBig = {"_p_p_GUIntBig", "GUIntBig **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_p_int = {"_p_p_int", "int **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_void = {"_p_void", "VSILFILE *|void *", 0, 0, (void*)0, 0};
 
 static swig_type_info *swig_type_initial[] = {
@@ -22802,6 +22867,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_GDALRasterBandShadow,
   &_swigt__p_GDALTransformerInfoShadow,
   &_swigt__p_GDAL_GCP,
+  &_swigt__p_GUIntBig,
   &_swigt__p_OGRLayerShadow,
   &_swigt__p_VSIStatBufL,
   &_swigt__p_char,
@@ -22810,8 +22876,8 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_int,
   &_swigt__p_p_GDALRasterBandShadow,
   &_swigt__p_p_GDAL_GCP,
+  &_swigt__p_p_GUIntBig,
   &_swigt__p_p_char,
-  &_swigt__p_p_int,
   &_swigt__p_void,
 };
 
@@ -22829,6 +22895,7 @@ static swig_cast_info _swigc__p_GDALRasterAttributeTableShadow[] = {  {&_swigt__
 static swig_cast_info _swigc__p_GDALRasterBandShadow[] = {  {&_swigt__p_GDALRasterBandShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDALTransformerInfoShadow[] = {  {&_swigt__p_GDALTransformerInfoShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GDAL_GCP[] = {  {&_swigt__p_GDAL_GCP, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GUIntBig[] = {  {&_swigt__p_GUIntBig, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRLayerShadow[] = {  {&_swigt__p_OGRLayerShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_VSIStatBufL[] = {  {&_swigt__p_VSIStatBufL, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
@@ -22837,8 +22904,8 @@ static swig_cast_info _swigc__p_f_double_p_q_const__char_p_void__int[] = {  {&_s
 static swig_cast_info _swigc__p_int[] = {  {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_p_GDALRasterBandShadow[] = {  {&_swigt__p_p_GDALRasterBandShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_p_GDAL_GCP[] = {  {&_swigt__p_p_GDAL_GCP, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_p_GUIntBig[] = {  {&_swigt__p_p_GUIntBig, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_p_char[] = {  {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_p_int[] = {  {&_swigt__p_p_int, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_void[] = {  {&_swigt__p_void, 0, 0, 0},{0, 0, 0, 0}};
 
 static swig_cast_info *swig_cast_initial[] = {
@@ -22856,6 +22923,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_GDALRasterBandShadow,
   _swigc__p_GDALTransformerInfoShadow,
   _swigc__p_GDAL_GCP,
+  _swigc__p_GUIntBig,
   _swigc__p_OGRLayerShadow,
   _swigc__p_VSIStatBufL,
   _swigc__p_char,
@@ -22864,8 +22932,8 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_int,
   _swigc__p_p_GDALRasterBandShadow,
   _swigc__p_p_GDAL_GCP,
+  _swigc__p_p_GUIntBig,
   _swigc__p_p_char,
-  _swigc__p_p_int,
   _swigc__p_void,
 };
 
diff --git a/swig/perl/index.dox b/swig/perl/index.dox
index 80fac8a..157292d 100644
--- a/swig/perl/index.dox
+++ b/swig/perl/index.dox
@@ -96,7 +96,7 @@ Geo::GDAL::Class::subroutine();
 The disctinction between class methods and subroutines is subtle but
 often important. The method invocation passes the class name as the
 first argument while the subroutine invocation does not. Especially
-constructors (new and create) must be called as class methods.
+constructor (new) must be called as a class method.
 
 Similar to methods, also attributes are either class attributes or
 object attributes. Class attributes are global variables that are
@@ -133,7 +133,7 @@ caught by signal \_\_WARN\_\_. Examples:
 
 \code
 eval {
-    $point = Geo::OGR::Geometry->create(WKT=>"POINTXX(1 1)");
+    $point = Geo::OGR::Geometry->new(WKT=>"POINTXX(1 1)");
 };
 print STDERR "Error: $@";
 \endcode
diff --git a/swig/perl/lib/Geo/GDAL.dox b/swig/perl/lib/Geo/GDAL.dox
index 1060f4f..e8afbc3 100644
--- a/swig/perl/lib/Geo/GDAL.dox
+++ b/swig/perl/lib/Geo/GDAL.dox
@@ -1147,7 +1147,7 @@ sub traverse {
 #
 # Usage:
 # \code
-# $ct = Geo::GDAL::ColorTable->create(...arguments...);
+# $ct = Geo::GDAL::ColorTable->new(...arguments...);
 # \endcode
 # @return a new Geo::GDAL::ColorTable object
 
diff --git a/swig/perl/lib/Geo/GDAL.pm b/swig/perl/lib/Geo/GDAL.pm
index d47f6c9..fc5d67b 100644
--- a/swig/perl/lib/Geo/GDAL.pm
+++ b/swig/perl/lib/Geo/GDAL.pm
@@ -1837,7 +1837,12 @@ sub Write {
 
 sub Close {
     my ($self, $data) = @_;
-    Geo::GDAL::VSIFCloseL($self);
+    eval {
+        Geo::GDAL::VSIFCloseL($self);
+    };
+    if ($@) {
+        confess "Cannot close file: $@.";
+    }
 }
 
 sub Read {
@@ -1857,14 +1862,25 @@ sub Tell {
 
 sub Truncate {
     my ($self, $new_size) = @_;
-    Geo::GDAL::VSIFTruncateL($self, $new_size);
+    eval {
+        Geo::GDAL::VSIFTruncateL($self, $new_size);
+    };
+    if ($@) {
+        confess "Cannot truncate file: $@.";
+    }
 }
 
-sub Mkdir {
-    my ($path, $mode) = @_;
-    Geo::GDAL::Mkdir($path, $mode);
+sub MkDir {
+    my ($path) = @_;
+    my $mode = 0; # unused in CPL
+    eval {
+        Geo::GDAL::Mkdir($path, $mode);
+    };
+    if ($@) {
+        confess "Cannot make directory \"$path\": $@.";
+    }
 }
-*MkDir = *Mkdir;
+*Mkdir = *MkDir;
 
 sub ReadDir {
     my ($path) = @_;
@@ -1878,37 +1894,58 @@ sub ReadDirRecursive {
 
 sub Rename {
     my ($old, $new) = @_;
-    Geo::GDAL::Rename($old, $new);
+    eval {
+        Geo::GDAL::Rename($old, $new);
+    };
+    if ($@) {
+        confess "Cannot rename file \"$old\": $@.";
+    }
 }
 
-sub Rmdir {
+sub RmDir {
     my ($dirname, $recursive) = @_;
-    if (!$recursive) {
-        Geo::GDAL::Rmdir($dirname);
-    } else {
-        for my $f (ReadDir($dirname)) {
-            next if $f eq '..' or $f eq '.';
-            my @s = Stat($dirname.'/'.$f);
-            if ($s[0] eq 'f') {
-                Unlink($dirname.'/'.$f);
-            } elsif ($s[0] eq 'd') {
-                Rmdir($dirname.'/'.$f, 1);
-                Rmdir($dirname.'/'.$f);
+    eval {
+        if (!$recursive) {
+            Geo::GDAL::Rmdir($dirname);
+        } else {
+            for my $f (ReadDir($dirname)) {
+                next if $f eq '..' or $f eq '.';
+                my @s = Stat($dirname.'/'.$f);
+                if ($s[0] eq 'f') {
+                    Unlink($dirname.'/'.$f);
+                } elsif ($s[0] eq 'd') {
+                    Rmdir($dirname.'/'.$f, 1);
+                    Rmdir($dirname.'/'.$f);
+                }
             }
+            RmDir($dirname);
         }
-        Rmdir($dirname);
+    };
+    if ($@) {
+        my $r = $recursive ? ' recursively' : '';
+        confess "Cannot remove directory \"$dirname\"$r: $@.";
     }
 }
-*RmDir = *Rmdir;
+*Rmdir = *RmDir;
 
 sub Stat {
     my ($path) = @_;
-    Geo::GDAL::Stat($path);
+    eval {
+        Geo::GDAL::Stat($path);
+    };
+    if ($@) {
+        confess "Cannot stat file \"$path\": $@.";
+    }
 }
 
 sub Unlink {
     my ($filename) = @_;
-    Geo::GDAL::Unlink($filename);
+    eval {
+        Geo::GDAL::Unlink($filename);
+    };
+    if ($@) {
+        confess "Cannot unlink file \"$filename\": $@.";
+    }
 }
 
 
diff --git a/swig/perl/lib/Geo/OGR.dox b/swig/perl/lib/Geo/OGR.dox
index a4bd5d9..ba8c30e 100644
--- a/swig/perl/lib/Geo/OGR.dox
+++ b/swig/perl/lib/Geo/OGR.dox
@@ -434,12 +434,12 @@
 
 ## @method CreateField(%params)
 # Create a field.
-# @param params as in Geo::OGR::FieldDefn::create or
-# Geo::OGR::GeomFieldDefn::create, plus ApproxOK (whose default is true).
+# @param params as in Geo::OGR::FieldDefn::new or
+# Geo::OGR::GeomFieldDefn::new, plus ApproxOK (whose default is true).
 
 ## @method AlterFieldDefn($name, %params)
 # @param field the name of the field to be altered.
-# @param params as in Geo::OGR::FieldDefn::create. Width and
+# @param params as in Geo::OGR::FieldDefn::new. Width and
 # Precision should be both or neither.
 # @note Only non-spatial fields can be altered.
 # @note Also the deprecated form AlterFieldDefn($field,
@@ -794,7 +794,7 @@
 # of the first spatial field.
 # @param geometry [optional] a Geo::OGR::Geometry object or a hash
 # array from which such can be created (using
-# Geo::OGR::Geometry::create)
+# Geo::OGR::Geometry::new)
 # @return in a non-void context the geometry in the feature
 # as a Geo::OGR::Geometry object.
 
@@ -860,7 +860,7 @@
 #
 # Example usage:
 # \code
-# $fd = Geo::OGR::FeatureDefn->create( 
+# $fd = Geo::OGR::FeatureDefn->new( 
 #     Name => "name",
 #     Fields => [{ Name => 'field1', Type => 'String' },
 #                { Name => 'geom', GeometryType => 'Point' }] );
@@ -1000,8 +1000,8 @@
 
 ## @method \%Schema(%params)
 # Get the schema or set parts of the schema
-# @param params [optional] as those in Geo::OGR::FieldDefn::create.
-# @return a reference to a hash whose keys are as those in Geo::OGR::FieldDefn::create.
+# @param params [optional] as those in Geo::OGR::FieldDefn::new.
+# @return a reference to a hash whose keys are as those in Geo::OGR::FieldDefn::new.
 
 ## @ignore GetName
 ## @ignore GetNameRef
@@ -1107,8 +1107,8 @@
 
 ## @method \%Schema(%params)
 # Get the schema or set parts of the schema.
-# @param params [optional] as those in Geo::OGR::GeomFieldDefn::create
-# @return a reference to a hash whose keys are as those in Geo::OGR::GeomFieldDefn::create
+# @param params [optional] as those in Geo::OGR::GeomFieldDefn::new.
+# @return a reference to a hash whose keys are as those in Geo::OGR::GeomFieldDefn::new.
 
 ## @method Type
 # @return the type of this geometry field. One of Geo::OGR::GeomFieldDefn::Types
@@ -1196,7 +1196,7 @@
 # @return a new Geo::OGR::Geometry object.
 # Usage:
 # \code
-# $g = Geo::OGR::Geometry->create(...arguments...);
+# $g = Geo::OGR::Geometry->new(...arguments...);
 # \endcode
 
 ## @cmethod Geo::OGR::Geometry ApproximateArcAngles(%params)
diff --git a/swig/perl/lib/Geo/OSR.dox b/swig/perl/lib/Geo/OSR.dox
index 95c15bb..8f9b871 100644
--- a/swig/perl/lib/Geo/OSR.dox
+++ b/swig/perl/lib/Geo/OSR.dox
@@ -82,7 +82,7 @@
 #
 # Usage:
 # \code
-# $sr = Geo::OSR::SpatialReference->create( key => value );
+# $sr = Geo::OSR::SpatialReference->new( key => value );
 # \endcode
 # @return a new Geo::OSR::SpatialReference object
 
diff --git a/swig/perl/transform.dox b/swig/perl/transform.dox
index fd17ba5..b5ef811 100644
--- a/swig/perl/transform.dox
+++ b/swig/perl/transform.dox
@@ -17,13 +17,13 @@ $lname = shift @ARGV;
 
 $datasource = Geo::OGR::Open($dsname) or die;
 $layer1 = $datasource->Layer($lname) or die;
-$sr1 = Geo::OSR::SpatialReference->create(EPSG => 2392);
+$sr1 = Geo::OSR::SpatialReference->new(EPSG => 2392);
 
 $dsname = shift @ARGV;
 $lname = shift @ARGV;
 
 $datasource = Geo::OGR::Driver('ESRI Shapefile')->Create($dsname) or die;
-$sr2 = Geo::OSR::SpatialReference->create(EPSG => 2393);
+$sr2 = Geo::OSR::SpatialReference->new(EPSG => 2393);
 $layer2 = $datasource->CreateLayer
     ({ Name => $lname, SRS => $sr2, GeometryType => $layer1->GetLayerDefn->GeometryType});
 $layer2->Schema( $layer1->Schema );
diff --git a/swig/python/extensions/gdal_wrap.cpp b/swig/python/extensions/gdal_wrap.cpp
index 9cb29a9..c1aa90b 100644
--- a/swig/python/extensions/gdal_wrap.cpp
+++ b/swig/python/extensions/gdal_wrap.cpp
@@ -2890,6 +2890,8 @@ typedef struct OGRStyleTableHS OGRStyleTableShadow;
 
 /* use this to not return the int returned by GDAL */
 typedef int RETURN_NONE;
+/* return value that is used for VSI methods that return -1 on error (and set errno) */
+typedef int VSI_RETVAL;
 
 
 
@@ -6875,7 +6877,7 @@ SWIGINTERN PyObject *_wrap_Unlink(PyObject *SWIGUNUSEDPARM(self), PyObject *args
   char *arg1 = (char *) 0 ;
   int bToFree1 = 0 ;
   PyObject * obj0 = 0 ;
-  int result;
+  VSI_RETVAL result;
   
   if (!PyArg_ParseTuple(args,(char *)"O:Unlink",&obj0)) SWIG_fail;
   {
@@ -6896,7 +6898,7 @@ SWIGINTERN PyObject *_wrap_Unlink(PyObject *SWIGUNUSEDPARM(self), PyObject *args
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)VSIUnlink((char const *)arg1);
+    result = VSIUnlink((char const *)arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -6952,7 +6954,7 @@ SWIGINTERN PyObject *_wrap_Mkdir(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
   int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  int result;
+  VSI_RETVAL result;
   
   if (!PyArg_ParseTuple(args,(char *)"OO:Mkdir",&obj0,&obj1)) SWIG_fail;
   {
@@ -6978,7 +6980,7 @@ SWIGINTERN PyObject *_wrap_Mkdir(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)VSIMkdir((char const *)arg1,arg2);
+    result = VSIMkdir((char const *)arg1,arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7006,7 +7008,7 @@ SWIGINTERN PyObject *_wrap_Rmdir(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
   char *arg1 = (char *) 0 ;
   int bToFree1 = 0 ;
   PyObject * obj0 = 0 ;
-  int result;
+  VSI_RETVAL result;
   
   if (!PyArg_ParseTuple(args,(char *)"O:Rmdir",&obj0)) SWIG_fail;
   {
@@ -7027,7 +7029,7 @@ SWIGINTERN PyObject *_wrap_Rmdir(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)VSIRmdir((char const *)arg1);
+    result = VSIRmdir((char const *)arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7062,7 +7064,7 @@ SWIGINTERN PyObject *_wrap_Rename(PyObject *SWIGUNUSEDPARM(self), PyObject *args
   int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
-  int result;
+  VSI_RETVAL result;
   
   if (!PyArg_ParseTuple(args,(char *)"OO:Rename",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
@@ -7079,7 +7081,7 @@ SWIGINTERN PyObject *_wrap_Rename(PyObject *SWIGUNUSEDPARM(self), PyObject *args
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)VSIRename((char const *)arg1,(char const *)arg2);
+    result = VSIRename((char const *)arg1,(char const *)arg2);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7425,6 +7427,7 @@ SWIGINTERN PyObject *_wrap_VSIFCloseL(PyObject *SWIGUNUSEDPARM(self), PyObject *
   VSILFILE *arg1 = (VSILFILE *) 0 ;
   int res1 ;
   PyObject * obj0 = 0 ;
+  VSI_RETVAL result;
   
   if (!PyArg_ParseTuple(args,(char *)"O:VSIFCloseL",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0,SWIG_as_voidptrptr(&arg1), 0, 0);
@@ -7435,7 +7438,7 @@ SWIGINTERN PyObject *_wrap_VSIFCloseL(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    VSIFCloseL(arg1);
+    result = VSIFCloseL(arg1);
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -7443,7 +7446,7 @@ SWIGINTERN PyObject *_wrap_VSIFCloseL(PyObject *SWIGUNUSEDPARM(self), PyObject *
       }
     }
   }
-  resultobj = SWIG_Py_Void();
+  resultobj = SWIG_From_int(static_cast< int >(result));
   return resultobj;
 fail:
   return NULL;
@@ -24163,11 +24166,11 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"CPLBinaryToHex", _wrap_CPLBinaryToHex, METH_VARARGS, (char *)"CPLBinaryToHex(int nBytes) -> retStringAndCPLFree"},
 	 { (char *)"CPLHexToBinary", _wrap_CPLHexToBinary, METH_VARARGS, (char *)"CPLHexToBinary(char pszHex, int pnBytes) -> GByte"},
 	 { (char *)"FileFromMemBuffer", _wrap_FileFromMemBuffer, METH_VARARGS, (char *)"FileFromMemBuffer(char utf8_path, int nBytes)"},
-	 { (char *)"Unlink", _wrap_Unlink, METH_VARARGS, (char *)"Unlink(char utf8_path) -> int"},
+	 { (char *)"Unlink", _wrap_Unlink, METH_VARARGS, (char *)"Unlink(char utf8_path) -> VSI_RETVAL"},
 	 { (char *)"HasThreadSupport", _wrap_HasThreadSupport, METH_VARARGS, (char *)"HasThreadSupport() -> int"},
-	 { (char *)"Mkdir", _wrap_Mkdir, METH_VARARGS, (char *)"Mkdir(char utf8_path, int mode) -> int"},
-	 { (char *)"Rmdir", _wrap_Rmdir, METH_VARARGS, (char *)"Rmdir(char utf8_path) -> int"},
-	 { (char *)"Rename", _wrap_Rename, METH_VARARGS, (char *)"Rename(char pszOld, char pszNew) -> int"},
+	 { (char *)"Mkdir", _wrap_Mkdir, METH_VARARGS, (char *)"Mkdir(char utf8_path, int mode) -> VSI_RETVAL"},
+	 { (char *)"Rmdir", _wrap_Rmdir, METH_VARARGS, (char *)"Rmdir(char utf8_path) -> VSI_RETVAL"},
+	 { (char *)"Rename", _wrap_Rename, METH_VARARGS, (char *)"Rename(char pszOld, char pszNew) -> VSI_RETVAL"},
 	 { (char *)"StatBuf_mode_get", _wrap_StatBuf_mode_get, METH_VARARGS, (char *)"StatBuf_mode_get(StatBuf self) -> int"},
 	 { (char *)"StatBuf_size_get", _wrap_StatBuf_size_get, METH_VARARGS, (char *)"StatBuf_size_get(StatBuf self) -> GIntBig"},
 	 { (char *)"StatBuf_mtime_get", _wrap_StatBuf_mtime_get, METH_VARARGS, (char *)"StatBuf_mtime_get(StatBuf self) -> GIntBig"},
@@ -24177,7 +24180,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"StatBuf_swigregister", StatBuf_swigregister, METH_VARARGS, NULL},
 	 { (char *)"VSIStatL", _wrap_VSIStatL, METH_VARARGS, (char *)"VSIStatL(char utf8_path, int nFlags = 0) -> int"},
 	 { (char *)"VSIFOpenL", _wrap_VSIFOpenL, METH_VARARGS, (char *)"VSIFOpenL(char utf8_path, char pszMode) -> VSILFILE"},
-	 { (char *)"VSIFCloseL", _wrap_VSIFCloseL, METH_VARARGS, (char *)"VSIFCloseL(VSILFILE arg0)"},
+	 { (char *)"VSIFCloseL", _wrap_VSIFCloseL, METH_VARARGS, (char *)"VSIFCloseL(VSILFILE arg0) -> VSI_RETVAL"},
 	 { (char *)"VSIFSeekL", _wrap_VSIFSeekL, METH_VARARGS, (char *)"VSIFSeekL(VSILFILE arg0, GIntBig arg1, int arg2) -> int"},
 	 { (char *)"VSIFTellL", _wrap_VSIFTellL, METH_VARARGS, (char *)"VSIFTellL(VSILFILE arg0) -> GIntBig"},
 	 { (char *)"VSIFTruncateL", _wrap_VSIFTruncateL, METH_VARARGS, (char *)"VSIFTruncateL(VSILFILE arg0, GIntBig arg1) -> int"},
diff --git a/swig/python/osgeo/gdal.py b/swig/python/osgeo/gdal.py
index b913927..0f27ae5 100644
--- a/swig/python/osgeo/gdal.py
+++ b/swig/python/osgeo/gdal.py
@@ -243,7 +243,7 @@ def FileFromMemBuffer(*args):
   return _gdal.FileFromMemBuffer(*args)
 
 def Unlink(*args):
-  """Unlink(char utf8_path) -> int"""
+  """Unlink(char utf8_path) -> VSI_RETVAL"""
   return _gdal.Unlink(*args)
 
 def HasThreadSupport(*args):
@@ -251,15 +251,15 @@ def HasThreadSupport(*args):
   return _gdal.HasThreadSupport(*args)
 
 def Mkdir(*args):
-  """Mkdir(char utf8_path, int mode) -> int"""
+  """Mkdir(char utf8_path, int mode) -> VSI_RETVAL"""
   return _gdal.Mkdir(*args)
 
 def Rmdir(*args):
-  """Rmdir(char utf8_path) -> int"""
+  """Rmdir(char utf8_path) -> VSI_RETVAL"""
   return _gdal.Rmdir(*args)
 
 def Rename(*args):
-  """Rename(char pszOld, char pszNew) -> int"""
+  """Rename(char pszOld, char pszNew) -> VSI_RETVAL"""
   return _gdal.Rename(*args)
 VSI_STAT_EXISTS_FLAG = _gdal.VSI_STAT_EXISTS_FLAG
 VSI_STAT_NATURE_FLAG = _gdal.VSI_STAT_NATURE_FLAG
@@ -301,7 +301,7 @@ def VSIFOpenL(*args):
   return _gdal.VSIFOpenL(*args)
 
 def VSIFCloseL(*args):
-  """VSIFCloseL(VSILFILE arg0)"""
+  """VSIFCloseL(VSILFILE arg0) -> VSI_RETVAL"""
   return _gdal.VSIFCloseL(*args)
 
 def VSIFSeekL(*args):
diff --git a/swig/python/samples/README b/swig/python/samples/README
index 5bc2c82..ea5d3e4 100644
--- a/swig/python/samples/README
+++ b/swig/python/samples/README
@@ -105,6 +105,8 @@ wcs_virtds_params.py    Generates MapServer WCS layer definition from a tileinde
 ogr_build_junction_table.py Create junction tables for layers coming from GML datasources
                             that reference other objects in _href fields
 
+gcps2ogr.py             Outputs GDAL GCPs as OGR points
+
 ------------------------------------------------------------------------------
 Ports of .c/.cpp utilities
 ------------------------------------------------------------------------------
diff --git a/swig/python/samples/gcps2ogr.py b/swig/python/samples/gcps2ogr.py
new file mode 100644
index 0000000..c6a0acd
--- /dev/null
+++ b/swig/python/samples/gcps2ogr.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#******************************************************************************
+#  $Id: gcps2ogr.py 29219 2015-05-21 10:01:42Z rouault $
+# 
+#  Project:  GDAL
+#  Purpose:  Outputs GDAL GCPs as OGR points
+#  Author:   Even Rouault, <even dot rouault at spatialys dot com>
+# 
+#******************************************************************************
+#  Copyright (c) 2015, Even Rouault, <even dot rouault at spatialys dot com>
+# 
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+#  and/or sell copies of the Software, and to permit persons to whom the
+#  Software is furnished to do so, subject to the following conditions:
+# 
+#  The above copyright notice and this permission notice shall be included
+#  in all copies or substantial portions of the Software.
+# 
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+#  DEALINGS IN THE SOFTWARE.
+#******************************************************************************
+
+from osgeo import gdal
+from osgeo import ogr
+from osgeo import osr
+import sys
+
+
+def Usage():
+    print('Usage: gcp2ogr.py [-f ogr_drv_name] gdal_in_dataset ogr_out_dataset')
+    sys.exit(1)
+
+out_format = 'ESRI Shapefile'
+in_dataset = None
+out_dataset = None
+i = 1
+while i < len(sys.argv):
+    if sys.argv[i] == '-f':
+        i+=1
+        out_format = sys.argv[i]
+    elif sys.argv[i][0] == '-':
+        Usage()
+    elif in_dataset is None:
+        in_dataset = sys.argv[i]
+    elif out_dataset is None:
+        out_dataset = sys.argv[i]
+    else:
+        Usage()
+    i+= 1
+
+if out_dataset is None:
+    Usage()
+
+ds = gdal.Open(in_dataset)
+out_ds = ogr.GetDriverByName('ESRI Shapefile').CreateDataSource(out_dataset)
+sr = None
+wkt = ds.GetGCPProjection()
+if wkt != '':
+    sr = osr.SpatialReference(wkt)
+out_lyr = out_ds.CreateLayer('gcps', geom_type = ogr.wkbPoint, srs = sr)
+out_lyr.CreateField(ogr.FieldDefn('Id', ogr.OFTString))
+out_lyr.CreateField(ogr.FieldDefn('Info', ogr.OFTString))
+out_lyr.CreateField(ogr.FieldDefn('X', ogr.OFTReal))
+out_lyr.CreateField(ogr.FieldDefn('Y', ogr.OFTReal))
+gcps = ds.GetGCPs()
+for i in range(len(gcps)):
+    f = ogr.Feature(out_lyr.GetLayerDefn())
+    f.SetField('Id', gcps[i].Id)
+    f.SetField('Info', gcps[i].Info)
+    f.SetField('X', gcps[i].GCPPixel)
+    f.SetField('Y', gcps[i].GCPLine)
+    f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(%f %f)' % (gcps[i].GCPX, gcps[i].GCPY)))
+    out_lyr.CreateFeature(f)
+
diff --git a/swig/python/scripts/gdal_merge.py b/swig/python/scripts/gdal_merge.py
index c8a1100..6fd2570 100755
--- a/swig/python/scripts/gdal_merge.py
+++ b/swig/python/scripts/gdal_merge.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: gdal_merge.py 28137 2014-12-14 10:33:22Z rouault $
+# $Id: gdal_merge.py 29213 2015-05-20 11:52:44Z rouault $
 #
 # Project:  InSAR Peppers
 # Purpose:  Module to extract data from many rasters into one output.
@@ -56,11 +56,19 @@ def raster_copy( s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
                  t_fh, t_xoff, t_yoff, t_xsize, t_ysize, t_band_n,
                  nodata=None ):
 
-    if nodata is not None:
-        return raster_copy_with_nodata(
+    s_band = s_fh.GetRasterBand( s_band_n )
+    m_band = None
+    # Works only in binary mode and doesn't take into account
+    # intermediate transparency values for compositing
+    if s_band.GetMaskFlags() != gdal.GMF_ALL_VALID:
+        m_band = s_band.GetMaskBand()
+    elif s_band.GetColorInterpretation() == gdal.GCI_AlphaBand:
+        m_band = s_band
+    if m_band is not None:
+        return raster_copy_with_mask(
             s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
             t_fh, t_xoff, t_yoff, t_xsize, t_ysize, t_band_n,
-            nodata )
+            m_band )
 
     if verbose != 0:
         print('Copy %d,%d,%d,%d to %d,%d,%d,%d.' \
@@ -79,9 +87,9 @@ def raster_copy( s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
     return 0
     
 # =============================================================================
-def raster_copy_with_nodata( s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
-                             t_fh, t_xoff, t_yoff, t_xsize, t_ysize, t_band_n,
-                             nodata ):
+def raster_copy_with_mask( s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
+                           t_fh, t_xoff, t_yoff, t_xsize, t_ysize, t_band_n,
+                           m_band ):
     try:
         import numpy as Numeric
     except ImportError:
@@ -97,10 +105,12 @@ def raster_copy_with_nodata( s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
 
     data_src = s_band.ReadAsArray( s_xoff, s_yoff, s_xsize, s_ysize,
                                    t_xsize, t_ysize )
+    data_mask = m_band.ReadAsArray( s_xoff, s_yoff, s_xsize, s_ysize,
+                                    t_xsize, t_ysize )
     data_dst = t_band.ReadAsArray( t_xoff, t_yoff, t_xsize, t_ysize )
 
-    nodata_test = Numeric.equal(data_src,nodata)
-    to_write = Numeric.choose( nodata_test, (data_src, data_dst) )
+    mask_test = Numeric.equal(data_mask, 0)
+    to_write = Numeric.choose( mask_test, (data_src, data_dst) )
 
     t_band.WriteArray( to_write, t_xoff, t_yoff )
 

-- 
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