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