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

Generated by: LCOV version 1.14