LCOV - code coverage report
Current view: top level - frmts/wms - minidriver_wms.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 73 103 70.9 %
Date: 2025-07-09 17:50:03 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  WMS Client Driver
       4             :  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
       5             :  *           and other similar services.
       6             :  * Author:   Adam Nowacki, nowak@xpam.de
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2007, Adam Nowacki
      10             :  * Copyright (c) 2007-2012, Even Rouault <even dot rouault at spatialys.com>
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ****************************************************************************/
      14             : 
      15             : #include "wmsdriver.h"
      16             : #include "minidriver_wms.h"
      17             : 
      18             : #include <algorithm>
      19             : 
      20             : WMSMiniDriver_WMS::WMSMiniDriver_WMS() = default;
      21             : 
      22             : WMSMiniDriver_WMS::~WMSMiniDriver_WMS() = default;
      23             : 
      24           4 : static double GetBBoxCoord(const GDALWMSImageRequestInfo &iri, char what)
      25             : {
      26           4 :     switch (what)
      27             :     {
      28           1 :         case 'x':
      29           1 :             return std::min(iri.m_x0, iri.m_x1);
      30           1 :         case 'y':
      31           1 :             return std::min(iri.m_y0, iri.m_y1);
      32           1 :         case 'X':
      33           1 :             return std::max(iri.m_x0, iri.m_x1);
      34           1 :         case 'Y':
      35           1 :             return std::max(iri.m_y0, iri.m_y1);
      36             :     }
      37           0 :     return 0.0;
      38             : }
      39             : 
      40           2 : CPLErr WMSMiniDriver_WMS::Initialize(CPLXMLNode *config,
      41             :                                      CPL_UNUSED char **papszOpenOptions)
      42             : {
      43           2 :     CPLErr ret = CE_None;
      44             : 
      45             :     {
      46           2 :         const char *version = CPLGetXMLValue(config, "Version", "1.1.0");
      47           2 :         if (version[0] != '\0')
      48             :         {
      49           2 :             m_version = version;
      50           2 :             m_iversion = VersionStringToInt(version);
      51           2 :             if (m_iversion == -1)
      52             :             {
      53           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
      54             :                          "GDALWMS, WMS mini-driver: Invalid version.");
      55           0 :                 ret = CE_Failure;
      56             :             }
      57             :         }
      58             :         else
      59             :         {
      60           0 :             CPLError(CE_Failure, CPLE_AppDefined,
      61             :                      "GDALWMS, WMS mini-driver: Version missing.");
      62           0 :             ret = CE_Failure;
      63             :         }
      64             :     }
      65             : 
      66           2 :     if (ret == CE_None)
      67             :     {
      68           2 :         const char *base_url = CPLGetXMLValue(config, "ServerURL", "");
      69           2 :         if (base_url[0] != '\0')
      70             :         {
      71             :             /* Try the old name */
      72           2 :             base_url = CPLGetXMLValue(config, "ServerUrl", "");
      73             :         }
      74           2 :         if (base_url[0] != '\0')
      75             :         {
      76           2 :             m_base_url = base_url;
      77             :         }
      78             :         else
      79             :         {
      80           0 :             CPLError(CE_Failure, CPLE_AppDefined,
      81             :                      "GDALWMS, WMS mini-driver: ServerURL missing.");
      82           0 :             ret = CE_Failure;
      83             :         }
      84             :     }
      85             : 
      86           2 :     if (ret == CE_None)
      87             :     {
      88             :         /* SRS is WMS version 1.1 and earlier, if SRS is not set use default
      89             :            unless CRS is set CRS is WMS version 1.3, if CRS is not set use
      90             :            default unless SRS is set */
      91           2 :         const char *crs = CPLGetXMLValue(config, "CRS", "");
      92           2 :         const char *srs = CPLGetXMLValue(config, "SRS", "");
      93           2 :         if (m_iversion >= VersionStringToInt("1.3"))
      94             :         {
      95             :             /* Version 1.3 and above */
      96           0 :             if ((srs[0] != '\0') && (crs[0] == '\0'))
      97             :             {
      98           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
      99             :                          "GDALWMS, WMS mini-driver: WMS version 1.3 and above "
     100             :                          "expects CRS however SRS was set instead.");
     101           0 :                 ret = CE_Failure;
     102             :             }
     103           0 :             else if (crs[0] != '\0')
     104             :             {
     105           0 :                 m_crs = crs;
     106             :             }
     107             :             else
     108             :             {
     109           0 :                 m_crs = "EPSG:4326";
     110             :             }
     111             :         }
     112             :         else
     113             :         {
     114             :             /* Version 1.1.1 and below */
     115           2 :             if ((srs[0] == '\0') && (crs[0] != '\0'))
     116             :             {
     117           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     118             :                          "GDALWMS, WMS mini-driver: WMS version 1.1.1 and "
     119             :                          "below expects SRS however CRS was set instead.");
     120           0 :                 ret = CE_Failure;
     121             :             }
     122           2 :             else if (srs[0] != '\0')
     123             :             {
     124           2 :                 m_srs = srs;
     125             :             }
     126             :             else
     127             :             {
     128           0 :                 m_srs = "EPSG:4326";
     129             :             }
     130             :         }
     131             :     }
     132             : 
     133           2 :     if (ret == CE_None)
     134             :     {
     135           2 :         if (!m_srs.empty())
     136             :         {
     137           2 :             m_oSRS = ProjToSRS(m_srs);
     138             :         }
     139           0 :         else if (!m_crs.empty())
     140             :         {
     141           0 :             m_oSRS = ProjToSRS(m_crs);
     142             :         }
     143             :     }
     144             : 
     145           2 :     if (ret == CE_None)
     146             :     {
     147           2 :         m_image_format = CPLGetXMLValue(config, "ImageFormat", "image/jpeg");
     148             :         m_info_format =
     149           2 :             CPLGetConfigOption("WMS_INFO_FORMAT", "application/vnd.ogc.gml");
     150           2 :         m_layers = CPLGetXMLValue(config, "Layers", "");
     151           2 :         m_styles = CPLGetXMLValue(config, "Styles", "");
     152           2 :         m_transparent = CPLGetXMLValue(config, "Transparent", "");
     153             :         // the transparent flag needs to be "TRUE" or "FALSE" in upper case
     154             :         // according to the WMS spec so force upper case
     155           7 :         for (char &ch : m_transparent)
     156             :         {
     157           5 :             ch = static_cast<char>(toupper(static_cast<unsigned char>(ch)));
     158             :         }
     159             :     }
     160             : 
     161           2 :     if (ret == CE_None)
     162             :     {
     163           2 :         const char *bbox_order = CPLGetXMLValue(config, "BBoxOrder", "xyXY");
     164           2 :         if (bbox_order[0] != '\0')
     165             :         {
     166             :             int i;
     167          10 :             for (i = 0; i < 4; ++i)
     168             :             {
     169           8 :                 if ((bbox_order[i] != 'x') && (bbox_order[i] != 'y') &&
     170           4 :                     (bbox_order[i] != 'X') && (bbox_order[i] != 'Y'))
     171           0 :                     break;
     172             :             }
     173           2 :             if (i == 4)
     174             :             {
     175           2 :                 m_bbox_order = bbox_order;
     176             :             }
     177             :             else
     178             :             {
     179           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     180             :                          "GDALWMS, WMS mini-driver: Incorrect BBoxOrder.");
     181           0 :                 ret = CE_Failure;
     182             :             }
     183             :         }
     184             :         else
     185             :         {
     186           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     187             :                      "GDALWMS, WMS mini-driver: BBoxOrder missing.");
     188           0 :             ret = CE_Failure;
     189             :         }
     190             :     }
     191             : 
     192           2 :     return ret;
     193             : }
     194             : 
     195           2 : void WMSMiniDriver_WMS::GetCapabilities(WMSMiniDriverCapabilities *caps)
     196             : {
     197           2 :     caps->m_has_getinfo = 1;
     198           2 : }
     199             : 
     200           1 : void WMSMiniDriver_WMS::BuildURL(CPLString &url,
     201             :                                  const GDALWMSImageRequestInfo &iri,
     202             :                                  const char *pszRequest)
     203             : {
     204             :     // http://onearth.jpl.nasa.gov/wms.cgi?request=GetMap&width=1000&height=500&layers=modis,global_mosaic&styles=&srs=EPSG:4326&format=image/jpeg&bbox=-180.000000,-90.000000,180.000000,090.000000
     205           1 :     url = m_base_url;
     206             : 
     207           1 :     URLPrepare(url);
     208           1 :     url += "request=";
     209           1 :     url += pszRequest;
     210             : 
     211           1 :     if (url.ifind("service=") == std::string::npos)
     212           0 :         url += "&service=WMS";
     213             : 
     214           2 :     url += CPLOPrintf(
     215             :         "&version=%s&layers=%s&styles=%s&format=%s&width=%d&height=%d&bbox=%."
     216             :         "8f,%.8f,%.8f,%.8f",
     217             :         m_version.c_str(), m_layers.c_str(), m_styles.c_str(),
     218           1 :         m_image_format.c_str(), iri.m_sx, iri.m_sy,
     219           1 :         GetBBoxCoord(iri, m_bbox_order[0]), GetBBoxCoord(iri, m_bbox_order[1]),
     220           2 :         GetBBoxCoord(iri, m_bbox_order[2]), GetBBoxCoord(iri, m_bbox_order[3]));
     221             : 
     222           1 :     if (!m_srs.empty())
     223           1 :         url += CPLOPrintf("&srs=%s", m_srs.c_str());
     224           1 :     if (!m_crs.empty())
     225           0 :         url += CPLOPrintf("&crs=%s", m_crs.c_str());
     226           1 :     if (!m_transparent.empty())
     227           1 :         url += CPLOPrintf("&transparent=%s", m_transparent.c_str());
     228           1 : }
     229             : 
     230           1 : CPLErr WMSMiniDriver_WMS::TiledImageRequest(
     231             :     WMSHTTPRequest &request, const GDALWMSImageRequestInfo &iri,
     232             :     CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri)
     233             : {
     234           1 :     CPLString &url = request.URL;
     235           1 :     BuildURL(url, iri, "GetMap");
     236           1 :     return CE_None;
     237             : }
     238             : 
     239           0 : void WMSMiniDriver_WMS::GetTiledImageInfo(
     240             :     CPLString &url, const GDALWMSImageRequestInfo &iri,
     241             :     CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri, int nXInBlock,
     242             :     int nYInBlock)
     243             : {
     244           0 :     BuildURL(url, iri, "GetFeatureInfo");
     245           0 :     url += CPLOPrintf("&query_layers=%s&x=%d&y=%d&info_format=%s",
     246             :                       m_layers.c_str(), nXInBlock, nYInBlock,
     247           0 :                       m_info_format.c_str());
     248           0 : }

Generated by: LCOV version 1.14