LCOV - code coverage report
Current view: directory - frmts/wms - dataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 375 278 74.1 %
Date: 2013-03-30 Functions: 30 22 73.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: dataset.cpp 25776 2013-03-20 20:46:48Z rouault $
       3                 :  *
       4                 :  * Project:  WMS Client Driver
       5                 :  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
       6                 :  *           and other similar services.
       7                 :  * Author:   Adam Nowacki, nowak@xpam.de
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2007, Adam Nowacki
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************
      30                 :  *
      31                 :  * dataset.cpp:
      32                 :  * Initialization of the GDALWMSdriver, parsing the XML configuration file, 
      33                 :  * instantiation of the minidrivers and accessors used by minidrivers
      34                 :  *
      35                 :  ***************************************************************************/ 
      36                 : 
      37                 : 
      38                 : #include "stdinc.h"
      39                 : 
      40              14 : GDALWMSDataset::GDALWMSDataset() {
      41              14 :     m_mini_driver = 0;
      42              14 :     m_cache = 0;
      43              14 :     m_hint.m_valid = false;
      44              14 :     m_data_type = GDT_Byte;
      45              14 :     m_clamp_requests = true;
      46              14 :     m_unsafeSsl = false;
      47              14 :     m_data_window.m_sx = -1;
      48              14 :     nBands = 0;
      49              14 :     m_default_block_size_x = 1024;
      50              14 :     m_default_block_size_y = 1024;
      51              14 :     m_bNeedsDataWindow = TRUE;
      52              14 :     m_default_tile_count_x = 1;
      53              14 :     m_default_tile_count_y = 1;
      54              14 :     m_default_overview_count = -1;
      55              14 :     m_zeroblock_on_serverexceptions = 0;
      56              14 :     m_poColorTable = NULL;
      57              14 : }
      58                 : 
      59              14 : GDALWMSDataset::~GDALWMSDataset() {
      60              14 :     if (m_mini_driver) delete m_mini_driver;
      61              14 :     if (m_cache) delete m_cache;
      62              14 :     if (m_poColorTable) delete m_poColorTable;
      63              14 : }
      64                 : 
      65              14 : CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
      66              14 :     CPLErr ret = CE_None;
      67                 : 
      68              14 :     char* pszXML = CPLSerializeXMLTree( config );
      69              14 :     if (pszXML)
      70                 :     {
      71              14 :         m_osXML = pszXML;
      72              14 :         CPLFree(pszXML);
      73                 :     }
      74                 : 
      75                 :     // Initialize the minidriver, which can set parameters for the dataset using member functions
      76              14 :     CPLXMLNode *service_node = CPLGetXMLNode(config, "Service");
      77              14 :     if (service_node != NULL)
      78                 :     {
      79              14 :         const CPLString service_name = CPLGetXMLValue(service_node, "name", "");
      80              14 :         if (!service_name.empty())
      81                 :         {
      82              14 :             GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager();
      83              14 :             GDALWMSMiniDriverFactory *const mdf = mdm->Find(service_name);
      84              14 :             if (mdf != NULL)
      85                 :             {
      86              14 :                 m_mini_driver = mdf->New();
      87              14 :                 m_mini_driver->m_parent_dataset = this;
      88              14 :                 if (m_mini_driver->Initialize(service_node) == CE_None)
      89                 :                 {
      90              14 :                     m_mini_driver_caps.m_capabilities_version = -1;
      91              14 :                     m_mini_driver->GetCapabilities(&m_mini_driver_caps);
      92              14 :                     if (m_mini_driver_caps.m_capabilities_version == -1)
      93                 :                     {
      94               0 :                         CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Internal error, mini-driver capabilities version not set.");
      95               0 :                         ret = CE_Failure;
      96                 :                     }
      97                 :                 }
      98                 :                 else
      99                 :                 {
     100               0 :                     delete m_mini_driver;
     101               0 :                     m_mini_driver = NULL;
     102                 : 
     103               0 :                     CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize minidriver.");
     104               0 :                     ret = CE_Failure;
     105                 :                 }
     106                 :             }
     107                 :             else
     108                 :             {
     109                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     110               0 :                                 "GDALWMS: No mini-driver registered for '%s'.", service_name.c_str());
     111               0 :                 ret = CE_Failure;
     112                 :             }
     113                 :         }
     114                 :         else
     115                 :         {
     116               0 :             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
     117               0 :             ret = CE_Failure;
     118              14 :         }
     119                 :     }
     120                 :     else
     121                 :     {
     122               0 :         CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
     123               0 :         ret = CE_Failure;
     124                 :     }
     125                 : 
     126                 : 
     127                 :     /*
     128                 :     Parameters that could be set by minidriver already, based on server side information.
     129                 :     If the size is set, minidriver has done this already
     130                 :     A "server" side minidriver needs to set at least:
     131                 :       - Blocksize (x and y)
     132                 :       - Clamp flag (defaults to true)
     133                 :       - DataWindow
     134                 :       - Band Count
     135                 :       - Data Type
     136                 :     It should also initialize and register the bands and overviews.
     137                 :     */
     138                 : 
     139              14 :     if (m_data_window.m_sx<1)
     140                 :     {
     141              11 :         int nOverviews = 0;
     142                 : 
     143              11 :         if (ret == CE_None)
     144                 :         {
     145              11 :             m_block_size_x = atoi(CPLGetXMLValue(config, "BlockSizeX", CPLString().Printf("%d", m_default_block_size_x)));
     146              22 :             m_block_size_y = atoi(CPLGetXMLValue(config, "BlockSizeY", CPLString().Printf("%d", m_default_block_size_y)));
     147              22 :             if (m_block_size_x <= 0 || m_block_size_y <= 0)
     148                 :             {
     149               0 :                 CPLError( CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value in BlockSizeX or BlockSizeY" );
     150               0 :                 ret = CE_Failure;
     151                 :             }
     152                 :         }
     153                 : 
     154              11 :         if (ret == CE_None)
     155                 :         {
     156              11 :             m_clamp_requests = StrToBool(CPLGetXMLValue(config, "ClampRequests", "true"));
     157              11 :             if (m_clamp_requests<0)
     158                 :             {
     159               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ClampRequests, true/false expected.");
     160               0 :                 ret = CE_Failure;
     161                 :             }
     162                 :         }
     163                 : 
     164              11 :         if (ret == CE_None)
     165                 :         {
     166              11 :             CPLXMLNode *data_window_node = CPLGetXMLNode(config, "DataWindow");
     167              11 :             if (data_window_node == NULL && m_bNeedsDataWindow)
     168                 :             {
     169               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow missing.");
     170               0 :                 ret = CE_Failure;
     171                 :             }
     172                 :             else
     173                 :             {
     174              11 :                 CPLString osDefaultX0, osDefaultX1, osDefaultY0, osDefaultY1;
     175              11 :                 CPLString osDefaultTileCountX, osDefaultTileCountY, osDefaultTileLevel;
     176              11 :                 CPLString osDefaultOverviewCount;
     177              11 :                 osDefaultX0.Printf("%.8f", m_default_data_window.m_x0);
     178              11 :                 osDefaultX1.Printf("%.8f", m_default_data_window.m_x1);
     179              11 :                 osDefaultY0.Printf("%.8f", m_default_data_window.m_y0);
     180              11 :                 osDefaultY1.Printf("%.8f", m_default_data_window.m_y1);
     181              11 :                 osDefaultTileCountX.Printf("%d", m_default_tile_count_x);
     182              11 :                 osDefaultTileCountY.Printf("%d", m_default_tile_count_y);
     183              11 :                 if (m_default_data_window.m_tlevel >= 0)
     184               1 :                     osDefaultTileLevel.Printf("%d", m_default_data_window.m_tlevel);
     185              11 :                 if (m_default_overview_count >= 0)
     186               1 :                     osDefaultOverviewCount.Printf("%d", m_default_overview_count);
     187              11 :                 const char *overview_count = CPLGetXMLValue(config, "OverviewCount", osDefaultOverviewCount);
     188              11 :                 const char *ulx = CPLGetXMLValue(data_window_node, "UpperLeftX", osDefaultX0);
     189              11 :                 const char *uly = CPLGetXMLValue(data_window_node, "UpperLeftY", osDefaultY0);
     190              11 :                 const char *lrx = CPLGetXMLValue(data_window_node, "LowerRightX", osDefaultX1);
     191              11 :                 const char *lry = CPLGetXMLValue(data_window_node, "LowerRightY", osDefaultY1);
     192              11 :                 const char *sx = CPLGetXMLValue(data_window_node, "SizeX", "");
     193              11 :                 const char *sy = CPLGetXMLValue(data_window_node, "SizeY", "");
     194              11 :                 const char *tx = CPLGetXMLValue(data_window_node, "TileX", "0");
     195              11 :                 const char *ty = CPLGetXMLValue(data_window_node, "TileY", "0");
     196              11 :                 const char *tlevel = CPLGetXMLValue(data_window_node, "TileLevel", osDefaultTileLevel);
     197              11 :                 const char *str_tile_count_x = CPLGetXMLValue(data_window_node, "TileCountX", osDefaultTileCountX);
     198              11 :                 const char *str_tile_count_y = CPLGetXMLValue(data_window_node, "TileCountY", osDefaultTileCountY);
     199              11 :                 const char *y_origin = CPLGetXMLValue(data_window_node, "YOrigin", "default");
     200                 : 
     201              11 :                 if (ret == CE_None)
     202                 :                 {
     203              22 :                     if ((ulx[0] != '\0') && (uly[0] != '\0') && (lrx[0] != '\0') && (lry[0] != '\0'))
     204                 :                     {
     205              11 :                         m_data_window.m_x0 = atof(ulx);
     206              11 :                         m_data_window.m_y0 = atof(uly);
     207              11 :                         m_data_window.m_x1 = atof(lrx);
     208              11 :                         m_data_window.m_y1 = atof(lry);
     209                 :                     }
     210                 :                     else
     211                 :                     {
     212                 :                         CPLError(CE_Failure, CPLE_AppDefined,
     213               0 :                                  "GDALWMS: Mandatory elements of DataWindow missing: UpperLeftX, UpperLeftY, LowerRightX, LowerRightY.");
     214               0 :                         ret = CE_Failure;
     215                 :                     }
     216                 :                 }
     217                 : 
     218              11 :                 m_data_window.m_tlevel = atoi(tlevel);
     219                 : 
     220              11 :                 if (ret == CE_None)
     221                 :                 {
     222              16 :                     if ((sx[0] != '\0') && (sy[0] != '\0'))
     223                 :                     {
     224               5 :                         m_data_window.m_sx = atoi(sx);
     225               5 :                         m_data_window.m_sy = atoi(sy);
     226                 :                     }
     227              12 :                     else if ((tlevel[0] != '\0') && (str_tile_count_x[0] != '\0') && (str_tile_count_y[0] != '\0'))
     228                 :                     {
     229               6 :                         int tile_count_x = atoi(str_tile_count_x);
     230               6 :                         int tile_count_y = atoi(str_tile_count_y);
     231               6 :                         m_data_window.m_sx = tile_count_x * m_block_size_x * (1 << m_data_window.m_tlevel);
     232               6 :                         m_data_window.m_sy = tile_count_y * m_block_size_y * (1 << m_data_window.m_tlevel);
     233                 :                     }
     234                 :                     else
     235                 :                     {
     236                 :                         CPLError(CE_Failure, CPLE_AppDefined,
     237               0 :                                  "GDALWMS: Mandatory elements of DataWindow missing: SizeX, SizeY.");
     238               0 :                         ret = CE_Failure;
     239                 :                     }
     240                 :                 }
     241              11 :                 if (ret == CE_None)
     242                 :                 {
     243              22 :                     if ((tx[0] != '\0') && (ty[0] != '\0'))
     244                 :                     {
     245              11 :                         m_data_window.m_tx = atoi(tx);
     246              11 :                         m_data_window.m_ty = atoi(ty);
     247                 :                     }
     248                 :                     else
     249                 :                     {
     250                 :                         CPLError(CE_Failure, CPLE_AppDefined,
     251               0 :                                  "GDALWMS: Mandatory elements of DataWindow missing: TileX, TileY.");
     252               0 :                         ret = CE_Failure;
     253                 :                     }
     254                 :                 }
     255                 : 
     256              11 :                 if (ret == CE_None)
     257                 :                 {
     258              11 :                     if (overview_count[0] != '\0')
     259                 :                     {
     260               4 :                         nOverviews = atoi(overview_count);
     261                 :                     }
     262               7 :                     else if (tlevel[0] != '\0')
     263                 :                     {
     264               6 :                         nOverviews = m_data_window.m_tlevel;
     265                 :                     }
     266                 :                     else
     267                 :                     {
     268               1 :                         const int min_overview_size = MAX(32, MIN(m_block_size_x, m_block_size_y));
     269                 :                         double a = log(static_cast<double>(MIN(m_data_window.m_sx, m_data_window.m_sy))) / log(2.0)
     270               1 :                             - log(static_cast<double>(min_overview_size)) / log(2.0);
     271               1 :                         nOverviews = MAX(0, MIN(static_cast<int>(ceil(a)), 32));
     272                 :                     }
     273                 :                 }
     274              11 :                 if (ret == CE_None)
     275                 :                 {
     276              11 :                     CPLString y_origin_str = y_origin;
     277              11 :                     if (y_origin_str == "top") {
     278               2 :                         m_data_window.m_y_origin = GDALWMSDataWindow::TOP;
     279               9 :                     } else if (y_origin_str == "bottom") {
     280               0 :                         m_data_window.m_y_origin = GDALWMSDataWindow::BOTTOM;
     281               9 :                     } else if (y_origin_str == "default") {
     282               9 :                         m_data_window.m_y_origin = GDALWMSDataWindow::DEFAULT;
     283                 :                     } else {
     284                 :                         CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow YOrigin must be set to "
     285               0 :                             "one of 'default', 'top', or 'bottom', not '%s'.", y_origin_str.c_str());
     286               0 :                         ret = CE_Failure;
     287              11 :                     }
     288              11 :                 }
     289                 :             }
     290                 :         }
     291                 : 
     292              11 :         if (ret == CE_None)
     293                 :         {
     294              11 :             if (nBands<1)
     295              11 :                 nBands=atoi(CPLGetXMLValue(config,"BandsCount","3"));
     296              11 :             if (nBands<1)
     297                 :             {
     298                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     299               0 :                          "GDALWMS: Bad number of bands.");
     300               0 :                 ret = CE_Failure;
     301                 :             }
     302                 :         }
     303                 : 
     304              11 :         if (ret == CE_None)
     305                 :         {
     306              11 :             const char *data_type = CPLGetXMLValue(config, "DataType", "Byte");
     307              11 :             m_data_type = GDALGetDataTypeByName( data_type );
     308              11 :             if ( m_data_type == GDT_Unknown || m_data_type >= GDT_TypeCount )
     309                 :             {
     310                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     311               0 :                           "GDALWMS: Invalid value in DataType. Data type \"%s\" is not supported.", data_type );
     312               0 :                 ret = CE_Failure;
     313                 :             }
     314                 :         }
     315                 : 
     316                 :         // Initialize the bands and the overviews.  Assumes overviews are powers of two
     317              11 :         if (ret == CE_None)
     318                 :         {
     319              11 :             nRasterXSize = m_data_window.m_sx;
     320              11 :             nRasterYSize = m_data_window.m_sy;
     321                 : 
     322              11 :             if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize) ||
     323                 :                 !GDALCheckBandCount(nBands, TRUE))
     324                 :             {
     325               0 :                 return CE_Failure;
     326                 :             }
     327                 : 
     328                 :             GDALColorInterp default_color_interp[4][4] = {
     329                 :                 { GCI_GrayIndex, GCI_Undefined, GCI_Undefined, GCI_Undefined },
     330                 :                 { GCI_GrayIndex, GCI_AlphaBand, GCI_Undefined, GCI_Undefined },
     331                 :                 { GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_Undefined },
     332                 :                 { GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_AlphaBand }
     333              11 :             };
     334              44 :             for (int i = 0; i < nBands; ++i)
     335                 :             {
     336              33 :                 GDALColorInterp color_interp = (nBands <= 4 && i <= 3 ? default_color_interp[nBands - 1][i] : GCI_Undefined);
     337              33 :                 GDALWMSRasterBand *band = new GDALWMSRasterBand(this, i, 1.0);
     338              33 :                 band->m_color_interp = color_interp;
     339              33 :                 SetBand(i + 1, band);
     340              33 :                 double scale = 0.5;
     341             630 :                 for (int j = 0; j < nOverviews; ++j)
     342                 :                 {
     343             597 :                     band->AddOverview(scale);
     344             597 :                     band->m_color_interp = color_interp;
     345             597 :                     scale *= 0.5;
     346                 :                 }
     347                 :             }
     348                 :         }
     349                 :     }
     350                 :     
     351                 :     // UserPwd 
     352              14 :     const char *pszUserPwd = CPLGetXMLValue(config, "UserPwd", "");
     353              14 :     if (pszUserPwd[0] != '\0')
     354               0 :         m_osUserPwd = pszUserPwd;
     355                 : 
     356              14 :     const char *pszUserAgent = CPLGetXMLValue(config, "UserAgent", "");
     357              14 :     if (pszUserAgent[0] != '\0')
     358               0 :         m_osUserAgent = pszUserAgent;
     359                 :     
     360              14 :     const char *pszReferer = CPLGetXMLValue(config, "Referer", "");
     361              14 :     if (pszReferer[0] != '\0')
     362               0 :         m_osReferer = pszReferer;
     363                 :     
     364              14 :     if (ret == CE_None) {
     365              14 :         const char *pszHttpZeroBlockCodes = CPLGetXMLValue(config, "ZeroBlockHttpCodes", "");
     366              14 :         if(pszHttpZeroBlockCodes == '\0') {
     367               0 :             m_http_zeroblock_codes.push_back(204);
     368                 :         } else {
     369              14 :             char **kv = CSLTokenizeString2(pszHttpZeroBlockCodes,",",CSLT_HONOURSTRINGS);
     370              14 :             int nCount = CSLCount(kv);
     371              14 :             for(int i=0; i<nCount; i++) {
     372               0 :                 int code = atoi(kv[i]);
     373               0 :                 if(code <= 0) {
     374                 :                     CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockHttpCodes \"%s\", comma separated HTTP response codes expected.",
     375               0 :                             kv[i]);
     376               0 :                     ret = CE_Failure;
     377               0 :                     break;
     378                 :                 }
     379               0 :                 m_http_zeroblock_codes.push_back(code);
     380                 :             }
     381              14 :             CSLDestroy(kv);
     382                 :         }
     383                 :     }
     384                 : 
     385              14 :     if (ret == CE_None) {
     386              14 :         const char *pszZeroExceptions = CPLGetXMLValue(config, "ZeroBlockOnServerException", "");
     387              14 :         if(pszZeroExceptions[0] != '\0') {
     388               0 :             m_zeroblock_on_serverexceptions = StrToBool(pszZeroExceptions);
     389               0 :             if (m_zeroblock_on_serverexceptions == -1) {
     390                 :                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockOnServerException \"%s\", true/false expected.",
     391               0 :                      pszZeroExceptions);
     392               0 :                 ret = CE_Failure;
     393                 :             }
     394                 :         }
     395                 :     }
     396                 : 
     397              14 :     if (ret == CE_None) {
     398              14 :         const char *max_conn = CPLGetXMLValue(config, "MaxConnections", "");
     399              14 :         if (max_conn[0] != '\0') {
     400               0 :             m_http_max_conn = atoi(max_conn);
     401                 :         } else {
     402              14 :             m_http_max_conn = 2;
     403                 :         }
     404                 :     }
     405              14 :     if (ret == CE_None) {
     406              14 :         const char *timeout = CPLGetXMLValue(config, "Timeout", "");
     407              14 :         if (timeout[0] != '\0') {
     408               0 :             m_http_timeout = atoi(timeout);
     409                 :         } else {
     410              14 :             m_http_timeout = 300;
     411                 :         }
     412                 :     }
     413              14 :     if (ret == CE_None) {
     414              14 :         const char *offline_mode = CPLGetXMLValue(config, "OfflineMode", "");
     415              14 :         if (offline_mode[0] != '\0') {
     416               0 :             const int offline_mode_bool = StrToBool(offline_mode);
     417               0 :             if (offline_mode_bool == -1) {
     418               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of OfflineMode, true / false expected.");
     419               0 :                 ret = CE_Failure;
     420                 :             } else {
     421               0 :                 m_offline_mode = offline_mode_bool;
     422                 :             }
     423                 :         } else {
     424              14 :             m_offline_mode = 0;
     425                 :         }
     426                 :     }
     427                 : 
     428              14 :     if (ret == CE_None) {
     429              14 :         const char *advise_read = CPLGetXMLValue(config, "AdviseRead", "");
     430              14 :         if (advise_read[0] != '\0') {
     431               0 :             const int advise_read_bool = StrToBool(advise_read);
     432               0 :             if (advise_read_bool == -1) {
     433               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of AdviseRead, true / false expected.");
     434               0 :                 ret = CE_Failure;
     435                 :             } else {
     436               0 :                 m_use_advise_read = advise_read_bool;
     437                 :             }
     438                 :         } else {
     439              14 :             m_use_advise_read = 0;
     440                 :         }
     441                 :     }
     442                 : 
     443              14 :     if (ret == CE_None) {
     444              14 :         const char *verify_advise_read = CPLGetXMLValue(config, "VerifyAdviseRead", "");
     445              14 :         if (m_use_advise_read) {
     446               0 :             if (verify_advise_read[0] != '\0') {
     447               0 :                 const int verify_advise_read_bool = StrToBool(verify_advise_read);
     448               0 :                 if (verify_advise_read_bool == -1) {
     449               0 :                     CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of VerifyAdviseRead, true / false expected.");
     450               0 :                     ret = CE_Failure;
     451                 :                 } else {
     452               0 :                     m_verify_advise_read = verify_advise_read_bool;
     453                 :                 }
     454                 :             } else {
     455               0 :                 m_verify_advise_read = 1;
     456                 :             }
     457                 :         }
     458                 :     }
     459                 : 
     460                 :     // Let the local configuration override the minidriver supplied projection
     461                 : 
     462              14 :     if (ret == CE_None) {
     463              14 :         const char *proj = CPLGetXMLValue(config, "Projection", "");
     464              14 :         if (proj[0] != '\0') {
     465               8 :             m_projection = ProjToWKT(proj);
     466               8 :             if (m_projection.size() == 0) {
     467               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Bad projection specified.");
     468               0 :                 ret = CE_Failure;
     469                 :             }
     470                 :         }
     471                 :     }
     472                 : 
     473                 :     // Same for Min, Max and NoData, defined per band or per dataset
     474                 :     // If they are set as null strings, they clear the server declared values
     475              14 :     if (ret == CE_None) {
     476                 :        // Data values are attributes, they include NoData Min and Max
     477                 :        // TODO: document those options
     478              14 :        if (0!=CPLGetXMLNode(config,"DataValues")) {
     479               0 :            const char *nodata=CPLGetXMLValue(config,"DataValues.NoData",NULL);
     480               0 :            if (nodata!=NULL) WMSSetNoDataValue(nodata);
     481               0 :            const char *min=CPLGetXMLValue(config,"DataValues.min",NULL);
     482               0 :            if (min!=NULL) WMSSetMinValue(min);
     483               0 :            const char *max=CPLGetXMLValue(config,"DataValues.max",NULL);
     484               0 :            if (max!=NULL) WMSSetMaxValue(max);
     485                 :        }
     486                 :     }
     487                 : 
     488              14 :     if (ret == CE_None) {
     489              14 :         CPLXMLNode *cache_node = CPLGetXMLNode(config, "Cache");
     490              14 :         if (cache_node != NULL) {
     491               4 :             m_cache = new GDALWMSCache();
     492               4 :             if (m_cache->Initialize(cache_node) != CE_None) {
     493               0 :                 delete m_cache;
     494               0 :                 m_cache = NULL;
     495               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize cache.");
     496               0 :                 ret = CE_Failure;
     497                 :             }
     498                 :         }
     499                 :     }
     500                 :     
     501              14 :     if (ret == CE_None) {
     502              14 :       const int v = StrToBool(CPLGetXMLValue(config, "UnsafeSSL", "false"));
     503              14 :       if (v == -1) {
     504               0 :       CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of UnsafeSSL: true or false expected.");
     505               0 :       ret = CE_Failure;
     506                 :   } else {
     507              14 :       m_unsafeSsl = v;
     508                 :   }
     509                 :     }
     510                 : 
     511              14 :     if (ret == CE_None) {
     512                 :         /* If we dont have projection already set ask mini-driver. */
     513              14 :         if (!m_projection.size()) {
     514               6 :             const char *proj = m_mini_driver->GetProjectionInWKT();
     515               6 :             if (proj != NULL) {
     516               6 :                 m_projection = proj;
     517                 :             }
     518                 :         }
     519                 :     }
     520                 : 
     521              14 :     return ret;
     522                 : }
     523                 : 
     524               1 : CPLErr GDALWMSDataset::IRasterIO(GDALRWFlag rw, int x0, int y0, int sx, int sy, void *buffer, int bsx, int bsy, GDALDataType bdt, int band_count, int *band_map, int pixel_space, int line_space, int band_space) {
     525                 :     CPLErr ret;
     526                 : 
     527               1 :     if (rw != GF_Read) return CE_Failure;
     528               1 :     if (buffer == NULL) return CE_Failure;
     529               1 :     if ((sx == 0) || (sy == 0) || (bsx == 0) || (bsy == 0) || (band_count == 0)) return CE_None;
     530                 : 
     531               1 :     m_hint.m_x0 = x0;
     532               1 :     m_hint.m_y0 = y0;
     533               1 :     m_hint.m_sx = sx;
     534               1 :     m_hint.m_sy = sy;
     535               1 :     m_hint.m_overview = -1;
     536               1 :     m_hint.m_valid = true;
     537                 :     //  printf("[%p] GDALWMSDataset::IRasterIO(x0: %d, y0: %d, sx: %d, sy: %d, bsx: %d, bsy: %d, band_count: %d, band_map: %p)\n", this, x0, y0, sx, sy, bsx, bsy, band_count, band_map);
     538               1 :     ret = GDALDataset::IRasterIO(rw, x0, y0, sx, sy, buffer, bsx, bsy, bdt, band_count, band_map, pixel_space, line_space, band_space);
     539               1 :     m_hint.m_valid = false;
     540                 : 
     541               1 :     return ret;
     542                 : }
     543                 : 
     544               2 : const char *GDALWMSDataset::GetProjectionRef() {
     545               2 :     return m_projection.c_str();
     546                 : }
     547                 : 
     548               0 : CPLErr GDALWMSDataset::SetProjection(const char *proj) {
     549               0 :     return CE_Failure;
     550                 : }
     551                 : 
     552               3 : CPLErr GDALWMSDataset::GetGeoTransform(double *gt) {
     553               3 :     gt[0] = m_data_window.m_x0;
     554               3 :     gt[1] = (m_data_window.m_x1 - m_data_window.m_x0) / static_cast<double>(m_data_window.m_sx);
     555               3 :     gt[2] = 0.0;
     556               3 :     gt[3] = m_data_window.m_y0;
     557               3 :     gt[4] = 0.0;
     558               3 :     gt[5] = (m_data_window.m_y1 - m_data_window.m_y0) / static_cast<double>(m_data_window.m_sy);
     559               3 :     return CE_None;
     560                 : }
     561                 : 
     562               0 : CPLErr GDALWMSDataset::SetGeoTransform(double *gt) {
     563               0 :     return CE_Failure;
     564                 : }
     565                 : 
     566               6 : const GDALWMSDataWindow *GDALWMSDataset::WMSGetDataWindow() const {
     567               6 :     return &m_data_window;
     568                 : }
     569                 : 
     570               3 : void GDALWMSDataset::WMSSetBlockSize(int x, int y) {
     571               3 :     m_block_size_x=x;
     572               3 :     m_block_size_y=y;
     573               3 : }
     574                 : 
     575               3 : void GDALWMSDataset::WMSSetRasterSize(int x, int y) {
     576               3 :     nRasterXSize=x;
     577               3 :     nRasterYSize=y;
     578               3 : }
     579                 : 
     580               3 : void GDALWMSDataset::WMSSetBandsCount(int count) {
     581               3 :     nBands=count;
     582               3 : }
     583                 : 
     584               3 : void GDALWMSDataset::WMSSetClamp(bool flag=true) {
     585               3 :     m_clamp_requests=flag;
     586               3 : }
     587                 : 
     588               3 : void GDALWMSDataset::WMSSetDataType(GDALDataType type) {
     589               3 :     m_data_type=type;
     590               3 : }
     591                 : 
     592               3 : void GDALWMSDataset::WMSSetDataWindow(GDALWMSDataWindow &window) {
     593               3 :     m_data_window=window;
     594               3 : }
     595                 : 
     596               1 : void GDALWMSDataset::WMSSetDefaultBlockSize(int x, int y) {
     597               1 :     m_default_block_size_x=x;
     598               1 :     m_default_block_size_y=y;
     599               1 : }
     600                 : 
     601               1 : void GDALWMSDataset::WMSSetDefaultDataWindowCoordinates(double x0, double y0, double x1, double y1)
     602                 : {
     603               1 :     m_default_data_window.m_x0 = x0;
     604               1 :     m_default_data_window.m_y0 = y0;
     605               1 :     m_default_data_window.m_x1 = x1;
     606               1 :     m_default_data_window.m_y1 = y1;
     607               1 : }
     608                 : 
     609               0 : void GDALWMSDataset::WMSSetDefaultTileCount(int tilecountx, int tilecounty)
     610                 : {
     611               0 :     m_default_tile_count_x = tilecountx;
     612               0 :     m_default_tile_count_y = tilecounty;
     613               0 : }
     614                 : 
     615               1 : void GDALWMSDataset::WMSSetDefaultTileLevel(int tlevel)
     616                 : {
     617               1 :     m_default_data_window.m_tlevel = tlevel;
     618               1 : }
     619                 : 
     620               1 : void GDALWMSDataset::WMSSetDefaultOverviewCount(int overview_count)
     621                 : {
     622               1 :     m_default_overview_count = overview_count;
     623               1 : }
     624                 : 
     625               1 : void GDALWMSDataset::WMSSetNeedsDataWindow(int flag)
     626                 : {
     627               1 :     m_bNeedsDataWindow = flag;
     628               1 : }
     629                 : 
     630               2 : static void list2vec(std::vector<double> &v,const char *pszList)
     631                 : {
     632               2 :     if ((pszList==NULL)||(pszList[0]==0)) return;
     633                 :     char **papszTokens=CSLTokenizeString2(pszList," \t\n\r",
     634               2 :         CSLT_STRIPLEADSPACES|CSLT_STRIPENDSPACES);
     635               2 :     v.clear();
     636               4 :     for (int i=0;i<CSLCount(papszTokens);i++)
     637               2 :         v.push_back(CPLStrtod(papszTokens[i],NULL));
     638               2 :     CSLDestroy(papszTokens);
     639                 : }
     640                 : 
     641               0 : void GDALWMSDataset::WMSSetNoDataValue(const char * pszNoData)
     642                 : {
     643               0 :     list2vec(vNoData,pszNoData);
     644               0 : }
     645                 : 
     646               1 : void GDALWMSDataset::WMSSetMinValue(const char * pszMin)
     647                 : {
     648               1 :     list2vec(vMin,pszMin);
     649               1 : }
     650                 : 
     651               1 : void GDALWMSDataset::WMSSetMaxValue(const char * pszMax)
     652                 : {
     653               1 :     list2vec(vMax,pszMax);
     654               1 : }
     655                 : 
     656               0 : CPLErr GDALWMSDataset::AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, int band_count, int *band_map, char **options) {
     657                 : //    printf("AdviseRead(%d, %d, %d, %d)\n", x0, y0, sx, sy);
     658               0 :     if (m_offline_mode || !m_use_advise_read) return CE_None;
     659               0 :     if (m_cache == NULL) return CE_Failure;
     660                 : 
     661               0 :     GDALRasterBand *band = GetRasterBand(1);
     662               0 :     if (band == NULL) return CE_Failure;
     663               0 :     return band->AdviseRead(x0, y0, sx, sy, bsx, bsy, bdt, options);
     664                 : }
     665                 : 
     666               1 : const char *GDALWMSDataset::GetMetadataItem( const char * pszName,
     667                 :                                              const char * pszDomain )
     668                 : {
     669               1 :     if( pszName != NULL && EQUAL(pszName, "XML") &&
     670                 :         pszDomain != NULL && EQUAL(pszDomain, "WMS") )
     671                 :     {
     672               1 :         return (m_osXML.size()) ? m_osXML.c_str() : NULL;
     673                 :     }
     674                 : 
     675               0 :     return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
     676                 : }

Generated by: LCOV version 1.7