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