LCOV - code coverage report
Current view: top level - frmts/wms - wmsdrivercore.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 90 97 92.8 %
Date: 2025-08-01 10:10:57 Functions: 8 8 100.0 %

          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) 2009-2014, Even Rouault <even dot rouault at spatialys.com>
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ****************************************************************************/
      14             : 
      15             : #include "wmsdrivercore.h"
      16             : 
      17             : /************************************************************************/
      18             : /*                     WMSDriverIdentify()                              */
      19             : /************************************************************************/
      20             : 
      21       60181 : int WMSDriverIdentify(GDALOpenInfo *poOpenInfo)
      22             : 
      23             : {
      24       60181 :     const char *pszFilename = poOpenInfo->pszFilename;
      25       60181 :     const char *pabyHeader =
      26             :         reinterpret_cast<const char *>(poOpenInfo->pabyHeader);
      27       60181 :     if (poOpenInfo->nHeaderBytes == 0 &&
      28       55390 :         STARTS_WITH_CI(pszFilename, "<GDAL_WMS>"))
      29             :     {
      30         670 :         return TRUE;
      31             :     }
      32       59511 :     else if (poOpenInfo->nHeaderBytes >= 10 &&
      33        4649 :              STARTS_WITH_CI(pabyHeader, "<GDAL_WMS>"))
      34             :     {
      35          21 :         return TRUE;
      36             :     }
      37      114210 :     else if (poOpenInfo->nHeaderBytes == 0 &&
      38       54720 :              (STARTS_WITH_CI(pszFilename, "WMS:") ||
      39      114208 :               CPLString(pszFilename).ifind("SERVICE=WMS") != std::string::npos))
      40             :     {
      41           2 :         return TRUE;
      42             :     }
      43      173694 :     else if (poOpenInfo->nHeaderBytes == 0 &&
      44       59509 :              poOpenInfo->IsSingleAllowedDriver("WMS") &&
      45          21 :              (STARTS_WITH(poOpenInfo->pszFilename, "http://") ||
      46          19 :               STARTS_WITH(poOpenInfo->pszFilename, "https://")))
      47             :     {
      48           2 :         return true;
      49             :     }
      50       59486 :     else if (poOpenInfo->nHeaderBytes != 0 &&
      51        4770 :              (strstr(pabyHeader, "<WMT_MS_Capabilities") != nullptr ||
      52        4770 :               strstr(pabyHeader, "<WMS_Capabilities") != nullptr ||
      53        4770 :               strstr(pabyHeader, "<!DOCTYPE WMT_MS_Capabilities") != nullptr))
      54             :     {
      55           0 :         return TRUE;
      56             :     }
      57       59486 :     else if (poOpenInfo->nHeaderBytes != 0 &&
      58        4770 :              strstr(pabyHeader, "<WMS_Tile_Service") != nullptr)
      59             :     {
      60           4 :         return TRUE;
      61             :     }
      62       59482 :     else if (poOpenInfo->nHeaderBytes != 0 &&
      63        4766 :              strstr(pabyHeader, "<TileMap version=\"1.0.0\"") != nullptr)
      64             :     {
      65           0 :         return TRUE;
      66             :     }
      67       59482 :     else if (poOpenInfo->nHeaderBytes != 0 &&
      68        4766 :              strstr(pabyHeader, "<Services") != nullptr &&
      69           0 :              strstr(pabyHeader, "<TileMapService version=\"1.0") != nullptr)
      70             :     {
      71           0 :         return TRUE;
      72             :     }
      73       59482 :     else if (poOpenInfo->nHeaderBytes != 0 &&
      74        4766 :              strstr(pabyHeader, "<TileMapService version=\"1.0.0\"") != nullptr)
      75             :     {
      76           0 :         return TRUE;
      77             :     }
      78       59482 :     else if (poOpenInfo->nHeaderBytes == 0 &&
      79       54716 :              STARTS_WITH_CI(pszFilename, "http") &&
      80          20 :              (strstr(pszFilename, "/MapServer?f=json") != nullptr ||
      81          18 :               strstr(pszFilename, "/MapServer/?f=json") != nullptr ||
      82          18 :               strstr(pszFilename, "/ImageServer?f=json") != nullptr ||
      83          18 :               strstr(pszFilename, "/ImageServer/?f=json") != nullptr))
      84             :     {
      85           2 :         return TRUE;
      86             :     }
      87       59480 :     else if (poOpenInfo->nHeaderBytes == 0 &&
      88       54714 :              STARTS_WITH_CI(pszFilename, "AGS:"))
      89             :     {
      90           0 :         return TRUE;
      91             :     }
      92       59480 :     else if (poOpenInfo->nHeaderBytes == 0 &&
      93       54714 :              STARTS_WITH_CI(pszFilename, "IIP:"))
      94             :     {
      95           2 :         return TRUE;
      96             :     }
      97       59478 :     else if (poOpenInfo->nHeaderBytes == 0 &&
      98       54712 :              STARTS_WITH_CI(pszFilename, "IIIF:"))
      99             :     {
     100           8 :         return TRUE;
     101             :     }
     102             :     else
     103       59470 :         return FALSE;
     104             : }
     105             : 
     106             : /************************************************************************/
     107             : /*                    OGRWMSDriverGetSubdatasetInfo()                   */
     108             : /************************************************************************/
     109             : 
     110             : struct WMSDriverSubdatasetInfo : public GDALSubdatasetInfo
     111             : {
     112             :   public:
     113           8 :     explicit WMSDriverSubdatasetInfo(const std::string &fileName)
     114           8 :         : GDALSubdatasetInfo(fileName)
     115             :     {
     116           8 :     }
     117             : 
     118             :     // GDALSubdatasetInfo interface
     119             :   private:
     120             :     void parseFileName() override;
     121             : };
     122             : 
     123           8 : void WMSDriverSubdatasetInfo::parseFileName()
     124             : {
     125           8 :     if (!STARTS_WITH_CI(m_fileName.c_str(), "WMS:"))
     126             :     {
     127           0 :         return;
     128             :     }
     129             : 
     130          16 :     const CPLString osLayers = CPLURLGetValue(m_fileName.c_str(), "LAYERS");
     131             : 
     132           8 :     if (!osLayers.empty())
     133             :     {
     134           6 :         m_subdatasetComponent = "LAYERS=" + osLayers;
     135           6 :         m_driverPrefixComponent = "WMS";
     136             : 
     137           6 :         m_pathComponent = m_fileName;
     138           6 :         m_pathComponent.erase(m_pathComponent.find(m_subdatasetComponent),
     139           6 :                               m_subdatasetComponent.length());
     140           6 :         m_pathComponent.erase(0, 4);
     141           6 :         const std::size_t nDoubleAndPos = m_pathComponent.find("&&");
     142           6 :         if (nDoubleAndPos != std::string::npos)
     143             :         {
     144           2 :             m_pathComponent.erase(nDoubleAndPos, 1);
     145             :         }
     146             :         // Reconstruct URL with LAYERS at the end or ModifyPathComponent will fail
     147          12 :         m_fileName = m_driverPrefixComponent + ":" + m_pathComponent + "&" +
     148          12 :                      m_subdatasetComponent;
     149             :     }
     150             : }
     151             : 
     152        2703 : static GDALSubdatasetInfo *WMSDriverGetSubdatasetInfo(const char *pszFileName)
     153             : {
     154        2703 :     if (STARTS_WITH(pszFileName, "WMS:"))
     155             :     {
     156             :         std::unique_ptr<GDALSubdatasetInfo> info =
     157           8 :             std::make_unique<WMSDriverSubdatasetInfo>(pszFileName);
     158          22 :         if (!info->GetSubdatasetComponent().empty() &&
     159          14 :             !info->GetPathComponent().empty())
     160             :         {
     161           6 :             return info.release();
     162             :         }
     163             :     }
     164        2697 :     return nullptr;
     165             : }
     166             : 
     167             : /************************************************************************/
     168             : /*                      WMSDriverSetCommonMetadata()                    */
     169             : /************************************************************************/
     170             : 
     171        1688 : void WMSDriverSetCommonMetadata(GDALDriver *poDriver)
     172             : {
     173        1688 :     poDriver->SetDescription(DRIVER_NAME);
     174        1688 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     175        1688 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "OGC Web Map Service");
     176        1688 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/wms.html");
     177        1688 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     178        1688 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
     179             : 
     180        1688 :     poDriver->pfnIdentify = WMSDriverIdentify;
     181        1688 :     poDriver->pfnGetSubdatasetInfoFunc = WMSDriverGetSubdatasetInfo;
     182        1688 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     183        1688 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
     184        1688 : }
     185             : 
     186             : /************************************************************************/
     187             : /*                     DeclareDeferredWMSPlugin()                       */
     188             : /************************************************************************/
     189             : 
     190             : #ifdef PLUGIN_FILENAME
     191        1961 : void DeclareDeferredWMSPlugin()
     192             : {
     193        1961 :     if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
     194             :     {
     195         283 :         return;
     196             :     }
     197        1678 :     auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     198             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     199             :     poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     200             :                               PLUGIN_INSTALLATION_MESSAGE);
     201             : #endif
     202        1678 :     WMSDriverSetCommonMetadata(poDriver);
     203        1678 :     GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     204             : }
     205             : #endif

Generated by: LCOV version 1.14