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