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) 2007-2012, Even Rouault <even dot rouault at spatialys.com>
11 : *
12 : * SPDX-License-Identifier: MIT
13 : ****************************************************************************/
14 :
15 : #include "wmsdriver.h"
16 : #include "minidriver_wms.h"
17 :
18 : #include <algorithm>
19 :
20 : WMSMiniDriver_WMS::WMSMiniDriver_WMS() = default;
21 :
22 : WMSMiniDriver_WMS::~WMSMiniDriver_WMS() = default;
23 :
24 4 : static double GetBBoxCoord(const GDALWMSImageRequestInfo &iri, char what)
25 : {
26 4 : switch (what)
27 : {
28 1 : case 'x':
29 1 : return std::min(iri.m_x0, iri.m_x1);
30 1 : case 'y':
31 1 : return std::min(iri.m_y0, iri.m_y1);
32 1 : case 'X':
33 1 : return std::max(iri.m_x0, iri.m_x1);
34 1 : case 'Y':
35 1 : return std::max(iri.m_y0, iri.m_y1);
36 : }
37 0 : return 0.0;
38 : }
39 :
40 2 : CPLErr WMSMiniDriver_WMS::Initialize(CPLXMLNode *config,
41 : CPL_UNUSED char **papszOpenOptions)
42 : {
43 2 : CPLErr ret = CE_None;
44 :
45 : {
46 2 : const char *version = CPLGetXMLValue(config, "Version", "1.1.0");
47 2 : if (version[0] != '\0')
48 : {
49 2 : m_version = version;
50 2 : m_iversion = VersionStringToInt(version);
51 2 : if (m_iversion == -1)
52 : {
53 0 : CPLError(CE_Failure, CPLE_AppDefined,
54 : "GDALWMS, WMS mini-driver: Invalid version.");
55 0 : ret = CE_Failure;
56 : }
57 : }
58 : else
59 : {
60 0 : CPLError(CE_Failure, CPLE_AppDefined,
61 : "GDALWMS, WMS mini-driver: Version missing.");
62 0 : ret = CE_Failure;
63 : }
64 : }
65 :
66 2 : if (ret == CE_None)
67 : {
68 2 : const char *base_url = CPLGetXMLValue(config, "ServerURL", "");
69 2 : if (base_url[0] != '\0')
70 : {
71 : /* Try the old name */
72 2 : base_url = CPLGetXMLValue(config, "ServerUrl", "");
73 : }
74 2 : if (base_url[0] != '\0')
75 : {
76 2 : m_base_url = base_url;
77 : }
78 : else
79 : {
80 0 : CPLError(CE_Failure, CPLE_AppDefined,
81 : "GDALWMS, WMS mini-driver: ServerURL missing.");
82 0 : ret = CE_Failure;
83 : }
84 : }
85 :
86 2 : if (ret == CE_None)
87 : {
88 : /* SRS is WMS version 1.1 and earlier, if SRS is not set use default
89 : unless CRS is set CRS is WMS version 1.3, if CRS is not set use
90 : default unless SRS is set */
91 2 : const char *crs = CPLGetXMLValue(config, "CRS", "");
92 2 : const char *srs = CPLGetXMLValue(config, "SRS", "");
93 2 : if (m_iversion >= VersionStringToInt("1.3"))
94 : {
95 : /* Version 1.3 and above */
96 0 : if ((srs[0] != '\0') && (crs[0] == '\0'))
97 : {
98 0 : CPLError(CE_Failure, CPLE_AppDefined,
99 : "GDALWMS, WMS mini-driver: WMS version 1.3 and above "
100 : "expects CRS however SRS was set instead.");
101 0 : ret = CE_Failure;
102 : }
103 0 : else if (crs[0] != '\0')
104 : {
105 0 : m_crs = crs;
106 : }
107 : else
108 : {
109 0 : m_crs = "EPSG:4326";
110 : }
111 : }
112 : else
113 : {
114 : /* Version 1.1.1 and below */
115 2 : if ((srs[0] == '\0') && (crs[0] != '\0'))
116 : {
117 0 : CPLError(CE_Failure, CPLE_AppDefined,
118 : "GDALWMS, WMS mini-driver: WMS version 1.1.1 and "
119 : "below expects SRS however CRS was set instead.");
120 0 : ret = CE_Failure;
121 : }
122 2 : else if (srs[0] != '\0')
123 : {
124 2 : m_srs = srs;
125 : }
126 : else
127 : {
128 0 : m_srs = "EPSG:4326";
129 : }
130 : }
131 : }
132 :
133 2 : if (ret == CE_None)
134 : {
135 2 : if (!m_srs.empty())
136 : {
137 2 : m_oSRS = ProjToSRS(m_srs);
138 : }
139 0 : else if (!m_crs.empty())
140 : {
141 0 : m_oSRS = ProjToSRS(m_crs);
142 : }
143 : }
144 :
145 2 : if (ret == CE_None)
146 : {
147 2 : m_image_format = CPLGetXMLValue(config, "ImageFormat", "image/jpeg");
148 : m_info_format =
149 2 : CPLGetConfigOption("WMS_INFO_FORMAT", "application/vnd.ogc.gml");
150 2 : m_layers = CPLGetXMLValue(config, "Layers", "");
151 2 : m_styles = CPLGetXMLValue(config, "Styles", "");
152 2 : m_transparent = CPLGetXMLValue(config, "Transparent", "");
153 : // the transparent flag needs to be "TRUE" or "FALSE" in upper case
154 : // according to the WMS spec so force upper case
155 7 : for (char &ch : m_transparent)
156 : {
157 5 : ch = static_cast<char>(toupper(static_cast<unsigned char>(ch)));
158 : }
159 : }
160 :
161 2 : if (ret == CE_None)
162 : {
163 2 : const char *bbox_order = CPLGetXMLValue(config, "BBoxOrder", "xyXY");
164 2 : if (bbox_order[0] != '\0')
165 : {
166 : int i;
167 10 : for (i = 0; i < 4; ++i)
168 : {
169 8 : if ((bbox_order[i] != 'x') && (bbox_order[i] != 'y') &&
170 4 : (bbox_order[i] != 'X') && (bbox_order[i] != 'Y'))
171 0 : break;
172 : }
173 2 : if (i == 4)
174 : {
175 2 : m_bbox_order = bbox_order;
176 : }
177 : else
178 : {
179 0 : CPLError(CE_Failure, CPLE_AppDefined,
180 : "GDALWMS, WMS mini-driver: Incorrect BBoxOrder.");
181 0 : ret = CE_Failure;
182 : }
183 : }
184 : else
185 : {
186 0 : CPLError(CE_Failure, CPLE_AppDefined,
187 : "GDALWMS, WMS mini-driver: BBoxOrder missing.");
188 0 : ret = CE_Failure;
189 : }
190 : }
191 :
192 2 : return ret;
193 : }
194 :
195 2 : void WMSMiniDriver_WMS::GetCapabilities(WMSMiniDriverCapabilities *caps)
196 : {
197 2 : caps->m_has_getinfo = 1;
198 2 : }
199 :
200 1 : void WMSMiniDriver_WMS::BuildURL(CPLString &url,
201 : const GDALWMSImageRequestInfo &iri,
202 : const char *pszRequest)
203 : {
204 : // http://onearth.jpl.nasa.gov/wms.cgi?request=GetMap&width=1000&height=500&layers=modis,global_mosaic&styles=&srs=EPSG:4326&format=image/jpeg&bbox=-180.000000,-90.000000,180.000000,090.000000
205 1 : url = m_base_url;
206 :
207 1 : URLPrepare(url);
208 1 : url += "request=";
209 1 : url += pszRequest;
210 :
211 1 : if (url.ifind("service=") == std::string::npos)
212 0 : url += "&service=WMS";
213 :
214 2 : url += CPLOPrintf(
215 : "&version=%s&layers=%s&styles=%s&format=%s&width=%d&height=%d&bbox=%."
216 : "8f,%.8f,%.8f,%.8f",
217 : m_version.c_str(), m_layers.c_str(), m_styles.c_str(),
218 1 : m_image_format.c_str(), iri.m_sx, iri.m_sy,
219 1 : GetBBoxCoord(iri, m_bbox_order[0]), GetBBoxCoord(iri, m_bbox_order[1]),
220 2 : GetBBoxCoord(iri, m_bbox_order[2]), GetBBoxCoord(iri, m_bbox_order[3]));
221 :
222 1 : if (!m_srs.empty())
223 1 : url += CPLOPrintf("&srs=%s", m_srs.c_str());
224 1 : if (!m_crs.empty())
225 0 : url += CPLOPrintf("&crs=%s", m_crs.c_str());
226 1 : if (!m_transparent.empty())
227 1 : url += CPLOPrintf("&transparent=%s", m_transparent.c_str());
228 1 : }
229 :
230 1 : CPLErr WMSMiniDriver_WMS::TiledImageRequest(
231 : WMSHTTPRequest &request, const GDALWMSImageRequestInfo &iri,
232 : CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri)
233 : {
234 1 : CPLString &url = request.URL;
235 1 : BuildURL(url, iri, "GetMap");
236 1 : return CE_None;
237 : }
238 :
239 0 : void WMSMiniDriver_WMS::GetTiledImageInfo(
240 : CPLString &url, const GDALWMSImageRequestInfo &iri,
241 : CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri, int nXInBlock,
242 : int nYInBlock)
243 : {
244 0 : BuildURL(url, iri, "GetFeatureInfo");
245 0 : url += CPLOPrintf("&query_layers=%s&x=%d&y=%d&info_format=%s",
246 : m_layers.c_str(), nXInBlock, nYInBlock,
247 0 : m_info_format.c_str());
248 0 : }
|