LCOV - code coverage report
Current view: directory - frmts/wms - wmsmetadataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 375 285 76.0 %
Date: 2012-12-26 Functions: 18 14 77.8 %

       1                 : /******************************************************************************
       2                 :  * $Id: wmsmetadataset.cpp 22576 2011-06-24 13:14:21Z warmerdam $
       3                 :  *
       4                 :  * Project:  WMS Client Driver
       5                 :  * Purpose:  Definition of GDALWMSMetaDataset class
       6                 :  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "wmsmetadataset.h"
      31                 : 
      32                 : int VersionStringToInt(const char *version);
      33                 : 
      34                 : /************************************************************************/
      35                 : /*                          GDALWMSMetaDataset()                        */
      36                 : /************************************************************************/
      37                 : 
      38               3 : GDALWMSMetaDataset::GDALWMSMetaDataset() : papszSubDatasets(NULL)
      39                 : {
      40               3 : }
      41                 : 
      42                 : /************************************************************************/
      43                 : /*                         ~GDALWMSMetaDataset()                        */
      44                 : /************************************************************************/
      45                 : 
      46               3 : GDALWMSMetaDataset::~GDALWMSMetaDataset()
      47                 : {
      48               3 :     CSLDestroy(papszSubDatasets);
      49               3 : }
      50                 : 
      51                 : /************************************************************************/
      52                 : /*                            AddSubDataset()                           */
      53                 : /************************************************************************/
      54                 : 
      55             123 : void GDALWMSMetaDataset::AddSubDataset(const char* pszName,
      56                 :                                        const char* pszDesc)
      57                 : {
      58                 :     char    szName[80];
      59             123 :     int     nCount = CSLCount(papszSubDatasets ) / 2;
      60                 : 
      61             123 :     sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
      62                 :     papszSubDatasets =
      63             123 :         CSLSetNameValue( papszSubDatasets, szName, pszName );
      64                 : 
      65             123 :     sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
      66                 :     papszSubDatasets =
      67             123 :         CSLSetNameValue( papszSubDatasets, szName, pszDesc);
      68             123 : }
      69                 : 
      70                 : /************************************************************************/
      71                 : /*                        DownloadGetCapabilities()                     */
      72                 : /************************************************************************/
      73                 : 
      74               1 : GDALDataset *GDALWMSMetaDataset::DownloadGetCapabilities(GDALOpenInfo *poOpenInfo)
      75                 : {
      76               1 :     const char* pszURL = poOpenInfo->pszFilename;
      77               1 :     if (EQUALN(pszURL, "WMS:", 4))
      78               1 :         pszURL += 4;
      79                 : 
      80               1 :     CPLString osFormat = CPLURLGetValue(pszURL, "FORMAT");
      81               1 :     CPLString osTransparent = CPLURLGetValue(pszURL, "TRANSPARENT");
      82               1 :     CPLString osVersion = CPLURLGetValue(pszURL, "VERSION");
      83                 : 
      84               1 :     if (osVersion.size() == 0)
      85               1 :         osVersion = "1.1.1";
      86                 : 
      87               1 :     CPLString osURL(pszURL);
      88               1 :     osURL = CPLURLAddKVP(osURL, "SERVICE", "WMS");
      89               1 :     osURL = CPLURLAddKVP(osURL, "VERSION", osVersion);
      90               1 :     osURL = CPLURLAddKVP(osURL, "REQUEST", "GetCapabilities");
      91                 :     /* Remove all other keywords */
      92               1 :     osURL = CPLURLAddKVP(osURL, "LAYERS", NULL);
      93               1 :     osURL = CPLURLAddKVP(osURL, "SRS", NULL);
      94               1 :     osURL = CPLURLAddKVP(osURL, "CRS", NULL);
      95               1 :     osURL = CPLURLAddKVP(osURL, "BBOX", NULL);
      96               1 :     osURL = CPLURLAddKVP(osURL, "FORMAT", NULL);
      97               1 :     osURL = CPLURLAddKVP(osURL, "TRANSPARENT", NULL);
      98               1 :     osURL = CPLURLAddKVP(osURL, "STYLES", NULL);
      99               1 :     osURL = CPLURLAddKVP(osURL, "WIDTH", NULL);
     100               1 :     osURL = CPLURLAddKVP(osURL, "HEIGHT", NULL);
     101                 : 
     102               1 :     CPLHTTPResult* psResult = CPLHTTPFetch( osURL, NULL );
     103               1 :     if (psResult == NULL)
     104                 :     {
     105               0 :         return NULL;
     106                 :     }
     107               1 :     if (psResult->nStatus != 0 || psResult->pszErrBuf != NULL)
     108                 :     {
     109                 :         CPLError(CE_Failure, CPLE_AppDefined,
     110                 :                  "Error returned by server : %s (%d)",
     111                 :                  (psResult->pszErrBuf) ? psResult->pszErrBuf : "unknown",
     112               0 :                  psResult->nStatus);
     113               0 :         CPLHTTPDestroyResult(psResult);
     114               0 :         return NULL;
     115                 :     }
     116               1 :     if (psResult->pabyData == NULL)
     117                 :     {
     118                 :         CPLError(CE_Failure, CPLE_AppDefined,
     119               0 :                  "Empty content returned by server");
     120               0 :         CPLHTTPDestroyResult(psResult);
     121               0 :         return NULL;
     122                 :     }
     123                 : 
     124               1 :     CPLXMLNode* psXML = CPLParseXMLString( (const char*) psResult->pabyData );
     125               1 :     if (psXML == NULL)
     126                 :     {
     127                 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid XML content : %s",
     128               0 :                 psResult->pabyData);
     129               0 :         CPLHTTPDestroyResult(psResult);
     130               0 :         return NULL;
     131                 :     }
     132                 : 
     133               1 :     GDALDataset* poRet = AnalyzeGetCapabilities(psXML, osFormat, osTransparent);
     134                 : 
     135               1 :     CPLHTTPDestroyResult(psResult);
     136               1 :     CPLDestroyXMLNode( psXML );
     137                 : 
     138               1 :     return poRet;
     139                 : }
     140                 : 
     141                 : 
     142                 : /************************************************************************/
     143                 : /*                         DownloadGetTileService()                     */
     144                 : /************************************************************************/
     145                 : 
     146               1 : GDALDataset *GDALWMSMetaDataset::DownloadGetTileService(GDALOpenInfo *poOpenInfo)
     147                 : {
     148               1 :     const char* pszURL = poOpenInfo->pszFilename;
     149               1 :     if (EQUALN(pszURL, "WMS:", 4))
     150               1 :         pszURL += 4;
     151                 : 
     152               1 :     CPLString osURL(pszURL);
     153               1 :     osURL = CPLURLAddKVP(osURL, "SERVICE", "WMS");
     154               1 :     osURL = CPLURLAddKVP(osURL, "REQUEST", "GetTileService");
     155                 :     /* Remove all other keywords */
     156               1 :     osURL = CPLURLAddKVP(osURL, "VERSION", NULL);
     157               1 :     osURL = CPLURLAddKVP(osURL, "LAYERS", NULL);
     158               1 :     osURL = CPLURLAddKVP(osURL, "SRS", NULL);
     159               1 :     osURL = CPLURLAddKVP(osURL, "CRS", NULL);
     160               1 :     osURL = CPLURLAddKVP(osURL, "BBOX", NULL);
     161               1 :     osURL = CPLURLAddKVP(osURL, "FORMAT", NULL);
     162               1 :     osURL = CPLURLAddKVP(osURL, "TRANSPARENT", NULL);
     163               1 :     osURL = CPLURLAddKVP(osURL, "STYLES", NULL);
     164               1 :     osURL = CPLURLAddKVP(osURL, "WIDTH", NULL);
     165               1 :     osURL = CPLURLAddKVP(osURL, "HEIGHT", NULL);
     166                 : 
     167               1 :     CPLHTTPResult* psResult = CPLHTTPFetch( osURL, NULL );
     168               1 :     if (psResult == NULL)
     169                 :     {
     170               0 :         return NULL;
     171                 :     }
     172               1 :     if (psResult->nStatus != 0 || psResult->pszErrBuf != NULL)
     173                 :     {
     174                 :         CPLError(CE_Failure, CPLE_AppDefined,
     175                 :                  "Error returned by server : %s (%d)",
     176                 :                  (psResult->pszErrBuf) ? psResult->pszErrBuf : "unknown",
     177               0 :                  psResult->nStatus);
     178               0 :         CPLHTTPDestroyResult(psResult);
     179               0 :         return NULL;
     180                 :     }
     181               1 :     if (psResult->pabyData == NULL)
     182                 :     {
     183                 :         CPLError(CE_Failure, CPLE_AppDefined,
     184               0 :                  "Empty content returned by server");
     185               0 :         CPLHTTPDestroyResult(psResult);
     186               0 :         return NULL;
     187                 :     }
     188                 : 
     189               1 :     CPLXMLNode* psXML = CPLParseXMLString( (const char*) psResult->pabyData );
     190               1 :     if (psXML == NULL)
     191                 :     {
     192                 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid XML content : %s",
     193               0 :                 psResult->pabyData);
     194               0 :         CPLHTTPDestroyResult(psResult);
     195               0 :         return NULL;
     196                 :     }
     197                 : 
     198               1 :     GDALDataset* poRet = AnalyzeGetTileService(psXML);
     199                 : 
     200               1 :     CPLHTTPDestroyResult(psResult);
     201               1 :     CPLDestroyXMLNode( psXML );
     202                 : 
     203               1 :     return poRet;
     204                 : }
     205                 : /************************************************************************/
     206                 : /*                            GetMetadata()                             */
     207                 : /************************************************************************/
     208                 : 
     209               3 : char **GDALWMSMetaDataset::GetMetadata( const char *pszDomain )
     210                 : 
     211                 : {
     212               3 :     if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
     213               3 :         return papszSubDatasets;
     214                 : 
     215               0 :     return GDALPamDataset::GetMetadata( pszDomain );
     216                 : }
     217                 : 
     218                 : /************************************************************************/
     219                 : /*                           AddSubDataset()                            */
     220                 : /************************************************************************/
     221                 : 
     222               0 : void GDALWMSMetaDataset::AddSubDataset( const char* pszLayerName,
     223                 :                                           const char* pszTitle,
     224                 :                                           const char* pszAbstract,
     225                 :                                           const char* pszSRS,
     226                 :                                           const char* pszMinX,
     227                 :                                           const char* pszMinY,
     228                 :                                           const char* pszMaxX,
     229                 :                                           const char* pszMaxY,
     230                 :                                           CPLString osFormat,
     231                 :                                           CPLString osTransparent)
     232                 : 
     233                 : {
     234               0 :     CPLString osSubdatasetName = "WMS:";
     235               0 :     osSubdatasetName += osGetURL;
     236               0 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "SERVICE", "WMS");
     237               0 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "VERSION", osVersion);
     238               0 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "REQUEST", "GetMap");
     239               0 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "LAYERS", pszLayerName);
     240               0 :     if(VersionStringToInt(osVersion.c_str())>= VersionStringToInt("1.3.0"))
     241                 :     {
     242               0 :         osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "CRS", pszSRS);
     243                 :         /* FIXME: this should apply to all SRS that need axis inversion */
     244               0 :         if (strcmp(pszSRS, "EPSG:4326") == 0)
     245               0 :             osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "BBOXORDER", "yxYX");
     246                 :     }
     247                 :     else
     248               0 :         osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "SRS", pszSRS);
     249                 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "BBOX",
     250               0 :              CPLSPrintf("%s,%s,%s,%s", pszMinX, pszMinY, pszMaxX, pszMaxY));
     251               0 :     if (osFormat.size() != 0)
     252                 :         osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "FORMAT",
     253               0 :                                         osFormat);
     254               0 :     if (osTransparent.size() != 0)
     255                 :         osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "TRANSPARENT",
     256               0 :                                         osTransparent);
     257                 : 
     258               0 :     if (pszTitle)
     259                 :     {
     260               0 :         if (osXMLEncoding.size() != 0 &&
     261                 :             osXMLEncoding != "utf-8" &&
     262                 :             osXMLEncoding != "UTF-8")
     263                 :         {
     264                 :             char* pszRecodedTitle = CPLRecode(pszTitle, osXMLEncoding.c_str(),
     265               0 :                                               CPL_ENC_UTF8);
     266               0 :             if (pszRecodedTitle)
     267               0 :                 AddSubDataset(osSubdatasetName, pszRecodedTitle);
     268                 :             else
     269               0 :                 AddSubDataset(osSubdatasetName, pszTitle);
     270               0 :             CPLFree(pszRecodedTitle);
     271                 :         }
     272                 :         else
     273                 :         {
     274               0 :             AddSubDataset(osSubdatasetName, pszTitle);
     275                 :         }
     276                 :     }
     277                 :     else
     278                 :     {
     279               0 :         AddSubDataset(osSubdatasetName, pszLayerName);
     280               0 :     }
     281               0 : }
     282                 : 
     283                 : 
     284                 : /************************************************************************/
     285                 : /*                         AddWMSCSubDataset()                          */
     286                 : /************************************************************************/
     287                 : 
     288              31 : void GDALWMSMetaDataset::AddWMSCSubDataset(WMSCTileSetDesc& oWMSCTileSetDesc,
     289                 :                                           const char* pszTitle,
     290                 :                                           CPLString osTransparent)
     291                 : {
     292              31 :     CPLString osSubdatasetName = "WMS:";
     293              31 :     osSubdatasetName += osGetURL;
     294              31 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "SERVICE", "WMS");
     295              31 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "VERSION", osVersion);
     296              31 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "REQUEST", "GetMap");
     297              31 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "LAYERS", oWMSCTileSetDesc.osLayers);
     298              31 :     if(VersionStringToInt(osVersion.c_str())>= VersionStringToInt("1.3.0"))
     299               0 :         osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "CRS", oWMSCTileSetDesc.osSRS);
     300                 :     else
     301              31 :         osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "SRS", oWMSCTileSetDesc.osSRS);
     302                 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "BBOX",
     303                 :              CPLSPrintf("%s,%s,%s,%s", oWMSCTileSetDesc.osMinX.c_str(),
     304                 :                                        oWMSCTileSetDesc.osMinY.c_str(),
     305                 :                                        oWMSCTileSetDesc.osMaxX.c_str(),
     306              31 :                                        oWMSCTileSetDesc.osMaxY.c_str()));
     307                 : 
     308              31 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "FORMAT", oWMSCTileSetDesc.osFormat);
     309              31 :     if (osTransparent.size() != 0)
     310                 :         osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "TRANSPARENT",
     311               0 :                                         osTransparent);
     312              31 :     if (oWMSCTileSetDesc.nTileWidth != oWMSCTileSetDesc.nTileHeight)
     313                 :         CPLDebug("WMS", "Weird: nTileWidth != nTileHeight for %s",
     314               0 :                  oWMSCTileSetDesc.osLayers.c_str());
     315                 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "TILESIZE",
     316              31 :                                     CPLSPrintf("%d", oWMSCTileSetDesc.nTileWidth));
     317                 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "OVERVIEWCOUNT",
     318              31 :                                     CPLSPrintf("%d", oWMSCTileSetDesc.nResolutions - 1));
     319                 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "MINRESOLUTION",
     320              31 :                                     CPLSPrintf("%.16f", oWMSCTileSetDesc.dfMinResolution));
     321              31 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "TILED", "true");
     322                 : 
     323              31 :     if (pszTitle)
     324                 :     {
     325              31 :         if (osXMLEncoding.size() != 0 &&
     326                 :             osXMLEncoding != "utf-8" &&
     327                 :             osXMLEncoding != "UTF-8")
     328                 :         {
     329                 :             char* pszRecodedTitle = CPLRecode(pszTitle, osXMLEncoding.c_str(),
     330               0 :                                               CPL_ENC_UTF8);
     331               0 :             if (pszRecodedTitle)
     332               0 :                 AddSubDataset(osSubdatasetName, pszRecodedTitle);
     333                 :             else
     334               0 :                 AddSubDataset(osSubdatasetName, pszTitle);
     335               0 :             CPLFree(pszRecodedTitle);
     336                 :         }
     337                 :         else
     338                 :         {
     339              31 :             AddSubDataset(osSubdatasetName, pszTitle);
     340                 :         }
     341                 :     }
     342                 :     else
     343                 :     {
     344               0 :         AddSubDataset(osSubdatasetName, oWMSCTileSetDesc.osLayers);
     345              31 :     }
     346              31 : }
     347                 : 
     348                 : /************************************************************************/
     349                 : /*                             ExploreLayer()                           */
     350                 : /************************************************************************/
     351                 : 
     352              32 : void GDALWMSMetaDataset::ExploreLayer(CPLXMLNode* psXML,
     353                 :                                       CPLString osFormat,
     354                 :                                       CPLString osTransparent,
     355                 :                                       const char* pszSRS,
     356                 :                                       const char* pszMinX,
     357                 :                                       const char* pszMinY,
     358                 :                                       const char* pszMaxX,
     359                 :                                       const char* pszMaxY)
     360                 : {
     361              32 :     const char* pszName = CPLGetXMLValue(psXML, "Name", NULL);
     362              32 :     const char* pszTitle = CPLGetXMLValue(psXML, "Title", NULL);
     363              32 :     const char* pszAbstract = CPLGetXMLValue(psXML, "Abstract", NULL);
     364                 : 
     365              32 :     const char* pszSRSLocal = NULL;
     366              32 :     const char* pszMinXLocal = NULL;
     367              32 :     const char* pszMinYLocal = NULL;
     368              32 :     const char* pszMaxXLocal = NULL;
     369              32 :     const char* pszMaxYLocal = NULL;
     370                 : 
     371                 :     const char* pszSRSTagName =
     372              32 :         VersionStringToInt(osVersion.c_str()) >= VersionStringToInt("1.3.0") ? "CRS" : "SRS";
     373                 : 
     374                 :     /* Use local bounding box if available, otherwise use the one */
     375                 :     /* that comes from an upper layer */
     376                 :     /* such as in http://neowms.sci.gsfc.nasa.gov/wms/wms */
     377              32 :     CPLXMLNode* psSRS = CPLGetXMLNode( psXML, "BoundingBox" );
     378              32 :     if (psSRS == NULL)
     379                 :     {
     380               1 :         psSRS = CPLGetXMLNode( psXML, "LatLonBoundingBox" );
     381               1 :         pszSRSLocal = CPLGetXMLValue(psXML, pszSRSTagName, NULL);
     382               1 :         if (pszSRSLocal == NULL)
     383               1 :             pszSRSLocal = "EPSG:4326";
     384                 :     }
     385                 :     else
     386              31 :         pszSRSLocal = CPLGetXMLValue(psSRS, pszSRSTagName, NULL);
     387                 : 
     388              32 :     if (pszSRSLocal != NULL && psSRS != NULL)
     389                 :     {
     390              32 :         pszMinXLocal = CPLGetXMLValue(psSRS, "minx", NULL);
     391              32 :         pszMinYLocal = CPLGetXMLValue(psSRS, "miny", NULL);
     392              32 :         pszMaxXLocal = CPLGetXMLValue(psSRS, "maxx", NULL);
     393              32 :         pszMaxYLocal = CPLGetXMLValue(psSRS, "maxy", NULL);
     394                 : 
     395              32 :         if (pszMinXLocal && pszMinYLocal && pszMaxXLocal && pszMaxYLocal)
     396                 :         {
     397              32 :             pszSRS = pszSRSLocal;
     398              32 :             pszMinX = pszMinXLocal;
     399              32 :             pszMinY = pszMinYLocal;
     400              32 :             pszMaxX = pszMaxXLocal;
     401              32 :             pszMaxY = pszMaxYLocal;
     402                 :         }
     403                 :     }
     404                 : 
     405              32 :     if (pszName != NULL && pszSRS && pszMinX && pszMinY && pszMaxX && pszMaxY)
     406                 :     {
     407              31 :         CPLString osLocalTransparent(osTransparent);
     408              31 :         if (osLocalTransparent.size() == 0)
     409                 :         {
     410              31 :             const char* pszOpaque = CPLGetXMLValue(psXML, "opaque", "0");
     411              31 :             if (EQUAL(pszOpaque, "1"))
     412               0 :                 osLocalTransparent = "FALSE";
     413                 :         }
     414                 : 
     415              31 :         WMSCKeyType oWMSCKey(pszName, pszSRS);
     416              31 :         std::map<WMSCKeyType, WMSCTileSetDesc>::iterator oIter = osMapWMSCTileSet.find(oWMSCKey);
     417              31 :         if (oIter != osMapWMSCTileSet.end())
     418                 :         {
     419              31 :             AddWMSCSubDataset(oIter->second, pszTitle, osLocalTransparent);
     420                 :         }
     421                 :         else
     422                 :         {
     423                 :             AddSubDataset(pszName, pszTitle, pszAbstract,
     424                 :                           pszSRS, pszMinX, pszMinY,
     425               0 :                           pszMaxX, pszMaxY, osFormat, osLocalTransparent);
     426              31 :         }
     427                 :     }
     428                 : 
     429              32 :     CPLXMLNode* psIter = psXML->psChild;
     430             345 :     for(; psIter != NULL; psIter = psIter->psNext)
     431                 :     {
     432             313 :         if (psIter->eType == CXT_Element)
     433                 :         {
     434             282 :             if (EQUAL(psIter->pszValue, "Layer"))
     435                 :                 ExploreLayer(psIter, osFormat, osTransparent,
     436              31 :                              pszSRS, pszMinX, pszMinY, pszMaxX, pszMaxY);
     437                 :         }
     438                 :     }
     439              32 : }
     440                 : 
     441                 : /************************************************************************/
     442                 : /*                         ParseWMSCTileSets()                          */
     443                 : /************************************************************************/
     444                 : 
     445               1 : void GDALWMSMetaDataset::ParseWMSCTileSets(CPLXMLNode* psXML)
     446                 : {
     447               1 :     CPLXMLNode* psIter = psXML->psChild;
     448             145 :     for(;psIter;psIter = psIter->psNext)
     449                 :     {
     450             144 :         if (psIter->eType == CXT_Element && EQUAL(psIter->pszValue, "TileSet"))
     451                 :         {
     452             144 :             const char* pszSRS = CPLGetXMLValue(psIter, "SRS", NULL);
     453             144 :             if (pszSRS == NULL)
     454               0 :                 continue;
     455                 : 
     456             144 :             CPLXMLNode* psBoundingBox = CPLGetXMLNode( psIter, "BoundingBox" );
     457             144 :             if (psBoundingBox == NULL)
     458               0 :                 continue;
     459                 : 
     460             144 :             const char* pszMinX = CPLGetXMLValue(psBoundingBox, "minx", NULL);
     461             144 :             const char* pszMinY = CPLGetXMLValue(psBoundingBox, "miny", NULL);
     462             144 :             const char* pszMaxX = CPLGetXMLValue(psBoundingBox, "maxx", NULL);
     463             144 :             const char* pszMaxY = CPLGetXMLValue(psBoundingBox, "maxy", NULL);
     464             144 :             if (pszMinX == NULL || pszMinY == NULL || pszMaxX == NULL || pszMaxY == NULL)
     465               0 :                 continue;
     466                 : 
     467             144 :             double dfMinX = CPLAtofM(pszMinX);
     468             144 :             double dfMinY = CPLAtofM(pszMinY);
     469             144 :             double dfMaxX = CPLAtofM(pszMaxX);
     470             144 :             double dfMaxY = CPLAtofM(pszMaxY);
     471             144 :             if (dfMaxY <= dfMinY || dfMaxX <= dfMinX)
     472               0 :                 continue;
     473                 : 
     474             144 :             const char* pszFormat = CPLGetXMLValue( psIter, "Format", NULL );
     475             144 :             if (pszFormat == NULL)
     476               0 :                 continue;
     477             144 :             if (strstr(pszFormat, "kml"))
     478               0 :                 continue;
     479                 : 
     480             144 :             const char* pszTileWidth = CPLGetXMLValue(psIter, "Width", NULL);
     481             144 :             const char* pszTileHeight = CPLGetXMLValue(psIter, "Height", NULL);
     482             144 :             if (pszTileWidth == NULL || pszTileHeight == NULL)
     483               0 :                 continue;
     484                 : 
     485             144 :             int nTileWidth = atoi(pszTileWidth);
     486             144 :             int nTileHeight = atoi(pszTileHeight);
     487             144 :             if (nTileWidth < 128 || nTileHeight < 128)
     488               0 :                 continue;
     489                 : 
     490             144 :             const char* pszLayers = CPLGetXMLValue(psIter, "Layers", NULL);
     491             144 :             if (pszLayers == NULL)
     492               0 :                 continue;
     493                 : 
     494             144 :             const char* pszResolutions = CPLGetXMLValue(psIter, "Resolutions", NULL);
     495             144 :             if (pszResolutions == NULL)
     496               0 :                 continue;
     497             144 :             char** papszTokens = CSLTokenizeStringComplex(pszResolutions, " ", 0, 0);
     498             144 :             double dfMinResolution = 0;
     499                 :             int i;
     500            3960 :             for(i=0; papszTokens && papszTokens[i]; i++)
     501                 :             {
     502            3816 :                 double dfResolution = CPLAtofM(papszTokens[i]);
     503            3816 :                 if (i==0 || dfResolution < dfMinResolution)
     504            3816 :                     dfMinResolution = dfResolution;
     505                 :             }
     506             144 :             CSLDestroy(papszTokens);
     507             144 :             int nResolutions = i;
     508             144 :             if (nResolutions == 0)
     509               0 :                 continue;
     510                 : 
     511             144 :             const char* pszStyles = CPLGetXMLValue(psIter, "Styles", "");
     512                 : 
     513                 :             /* http://demo.opengeo.org/geoserver/gwc/service/wms?tiled=TRUE&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetCapabilities */
     514                 :             /* has different variations of formats for the same (formats, SRS) tuple, so just */
     515                 :             /* keep the first one which is a png format */
     516             144 :             WMSCKeyType oWMSCKey(pszLayers, pszSRS);
     517             144 :             std::map<WMSCKeyType, WMSCTileSetDesc>::iterator oIter = osMapWMSCTileSet.find(oWMSCKey);
     518             144 :             if (oIter != osMapWMSCTileSet.end())
     519              82 :                 continue;
     520                 : 
     521              62 :             WMSCTileSetDesc oWMSCTileSet;
     522              62 :             oWMSCTileSet.osLayers = pszLayers;
     523              62 :             oWMSCTileSet.osSRS = pszSRS;
     524              62 :             oWMSCTileSet.osMinX = pszMinX;
     525              62 :             oWMSCTileSet.osMinY = pszMinY;
     526              62 :             oWMSCTileSet.osMaxX = pszMaxX;
     527              62 :             oWMSCTileSet.osMaxY = pszMaxY;
     528              62 :             oWMSCTileSet.dfMinX = dfMinX;
     529              62 :             oWMSCTileSet.dfMinY = dfMinY;
     530              62 :             oWMSCTileSet.dfMaxX = dfMaxX;
     531              62 :             oWMSCTileSet.dfMaxY = dfMaxY;
     532              62 :             oWMSCTileSet.nResolutions = nResolutions;
     533              62 :             oWMSCTileSet.dfMinResolution = dfMinResolution;
     534              62 :             oWMSCTileSet.osFormat = pszFormat;
     535              62 :             oWMSCTileSet.osStyle = pszStyles;
     536              62 :             oWMSCTileSet.nTileWidth = nTileWidth;
     537              62 :             oWMSCTileSet.nTileHeight = nTileHeight;
     538                 : 
     539              62 :             osMapWMSCTileSet[oWMSCKey] = oWMSCTileSet;
     540                 :         }
     541                 :     }
     542               1 : }
     543                 : 
     544                 : /************************************************************************/
     545                 : /*                        AnalyzeGetCapabilities()                      */
     546                 : /************************************************************************/
     547                 : 
     548               1 : GDALDataset* GDALWMSMetaDataset::AnalyzeGetCapabilities(CPLXMLNode* psXML,
     549                 :                                                           CPLString osFormat,
     550                 :                                                           CPLString osTransparent)
     551                 : {
     552               1 :     const char* pszEncoding = NULL;
     553               1 :     if (psXML->eType == CXT_Element && strcmp(psXML->pszValue, "?xml") == 0)
     554               1 :         pszEncoding = CPLGetXMLValue(psXML, "encoding", NULL);
     555                 : 
     556               1 :     CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=WMT_MS_Capabilities" );
     557               1 :     if (psRoot == NULL)
     558               0 :         psRoot = CPLGetXMLNode( psXML, "=WMS_Capabilities" );
     559               1 :     if (psRoot == NULL)
     560               0 :         return NULL;
     561               1 :     CPLXMLNode* psCapability = CPLGetXMLNode(psRoot, "Capability");
     562               1 :     if (psCapability == NULL)
     563               0 :         return NULL;
     564                 : 
     565                 :     CPLXMLNode* psOnlineResource = CPLGetXMLNode(psCapability,
     566               1 :                              "Request.GetMap.DCPType.HTTP.Get.OnlineResource");
     567               1 :     if (psOnlineResource == NULL)
     568               0 :         return NULL;
     569                 :     const char* pszGetURL =
     570               1 :         CPLGetXMLValue(psOnlineResource, "xlink:href", NULL);
     571               1 :     if (pszGetURL == NULL)
     572               0 :         return NULL;
     573                 : 
     574               1 :     CPLXMLNode* psLayer = CPLGetXMLNode(psCapability, "Layer");
     575               1 :     if (psLayer == NULL)
     576               0 :         return NULL;
     577                 : 
     578                 :     CPLXMLNode* psVendorSpecificCapabilities =
     579               1 :         CPLGetXMLNode(psCapability, "VendorSpecificCapabilities");
     580                 : 
     581               1 :     GDALWMSMetaDataset* poDS = new GDALWMSMetaDataset();
     582               1 :     const char* pszVersion = CPLGetXMLValue(psRoot, "version", NULL);
     583               1 :     if (pszVersion)
     584               1 :         poDS->osVersion = pszVersion;
     585                 :     else
     586               0 :         poDS->osVersion = "1.1.1";
     587               1 :     poDS->osGetURL = pszGetURL;
     588               2 :     poDS->osXMLEncoding = pszEncoding ? pszEncoding : "";
     589               1 :     if (psVendorSpecificCapabilities)
     590               1 :         poDS->ParseWMSCTileSets(psVendorSpecificCapabilities);
     591               1 :     poDS->ExploreLayer(psLayer, osFormat, osTransparent);
     592                 : 
     593               1 :     return poDS;
     594                 : }
     595                 : 
     596                 : /************************************************************************/
     597                 : /*                          AddTiledSubDataset()                        */
     598                 : /************************************************************************/
     599                 : 
     600              53 : void GDALWMSMetaDataset::AddTiledSubDataset(const char* pszTiledGroupName,
     601                 :                                             const char* pszTitle)
     602                 : {
     603              53 :     CPLString osSubdatasetName = "<GDAL_WMS><Service name=\"TiledWMS\"><ServerUrl>";
     604              53 :     osSubdatasetName += osGetURL;
     605              53 :     osSubdatasetName += "</ServerUrl><TiledGroupName>";
     606              53 :     osSubdatasetName += pszTiledGroupName;
     607              53 :     osSubdatasetName += "</TiledGroupName></Service></GDAL_WMS>";
     608                 : 
     609              53 :     if (pszTitle)
     610                 :     {
     611              53 :         if (osXMLEncoding.size() != 0 &&
     612                 :             osXMLEncoding != "utf-8" &&
     613                 :             osXMLEncoding != "UTF-8")
     614                 :         {
     615                 :             char* pszRecodedTitle = CPLRecode(pszTitle, osXMLEncoding.c_str(),
     616               0 :                                               CPL_ENC_UTF8);
     617               0 :             if (pszRecodedTitle)
     618               0 :                 AddSubDataset(osSubdatasetName, pszRecodedTitle);
     619                 :             else
     620               0 :                 AddSubDataset(osSubdatasetName, pszTitle);
     621               0 :             CPLFree(pszRecodedTitle);
     622                 :         }
     623                 :         else
     624                 :         {
     625              53 :             AddSubDataset(osSubdatasetName, pszTitle);
     626                 :         }
     627                 :     }
     628                 :     else
     629                 :     {
     630               0 :         AddSubDataset(osSubdatasetName, pszTiledGroupName);
     631              53 :     }
     632              53 : }
     633                 : 
     634                 : /************************************************************************/
     635                 : /*                     AnalyzeGetTileServiceRecurse()                   */
     636                 : /************************************************************************/
     637                 : 
     638               5 : void GDALWMSMetaDataset::AnalyzeGetTileServiceRecurse(CPLXMLNode* psXML)
     639                 : {
     640               5 :     CPLXMLNode* psIter = psXML->psChild;
     641              76 :     for(; psIter != NULL; psIter = psIter->psNext)
     642                 :     {
     643             124 :         if (psIter->eType == CXT_Element &&
     644                 :             EQUAL(psIter->pszValue, "TiledGroup"))
     645                 :         {
     646              53 :             const char* pszName = CPLGetXMLValue(psIter, "Name", NULL);
     647              53 :             const char* pszTitle = CPLGetXMLValue(psIter, "Title", NULL);
     648              53 :             if (pszName)
     649              53 :                 AddTiledSubDataset(pszName, pszTitle);
     650                 :         }
     651              18 :         else if (psIter->eType == CXT_Element &&
     652                 :             EQUAL(psIter->pszValue, "TiledGroups"))
     653                 :         {
     654               4 :             AnalyzeGetTileServiceRecurse(psIter);
     655                 :         }
     656                 :     }
     657               5 : }
     658                 : 
     659                 : /************************************************************************/
     660                 : /*                        AnalyzeGetTileService()                       */
     661                 : /************************************************************************/
     662                 : 
     663               1 : GDALDataset* GDALWMSMetaDataset::AnalyzeGetTileService(CPLXMLNode* psXML)
     664                 : {
     665               1 :     const char* pszEncoding = NULL;
     666               1 :     if (psXML->eType == CXT_Element && strcmp(psXML->pszValue, "?xml") == 0)
     667               0 :         pszEncoding = CPLGetXMLValue(psXML, "encoding", NULL);
     668                 : 
     669               1 :     CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=WMS_Tile_Service" );
     670               1 :     if (psRoot == NULL)
     671               0 :         return NULL;
     672               1 :     CPLXMLNode* psTiledPatterns = CPLGetXMLNode(psRoot, "TiledPatterns");
     673               1 :     if (psTiledPatterns == NULL)
     674               0 :         return NULL;
     675                 : 
     676                 :     const char* pszURL = CPLGetXMLValue(psTiledPatterns,
     677               1 :                                         "OnlineResource.xlink:href", NULL);
     678               1 :     if (pszURL == NULL)
     679               0 :         return NULL;
     680                 : 
     681               1 :     GDALWMSMetaDataset* poDS = new GDALWMSMetaDataset();
     682               2 :     poDS->osGetURL = pszURL;
     683               1 :     poDS->osXMLEncoding = pszEncoding ? pszEncoding : "";
     684                 : 
     685               1 :     poDS->AnalyzeGetTileServiceRecurse(psTiledPatterns);
     686                 : 
     687               1 :     return poDS;
     688                 : }
     689                 : 
     690                 : /************************************************************************/
     691                 : /*                        AnalyzeTileMapService()                       */
     692                 : /************************************************************************/
     693                 : 
     694               1 : GDALDataset* GDALWMSMetaDataset::AnalyzeTileMapService(CPLXMLNode* psXML)
     695                 : {
     696               1 :     CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=TileMapService" );
     697               1 :     if (psRoot == NULL)
     698               0 :         return NULL;
     699               1 :     CPLXMLNode* psTileMaps = CPLGetXMLNode(psRoot, "TileMaps");
     700               1 :     if (psTileMaps == NULL)
     701               0 :         return NULL;
     702                 : 
     703               1 :     GDALWMSMetaDataset* poDS = new GDALWMSMetaDataset();
     704                 : 
     705               1 :     CPLXMLNode* psIter = psTileMaps->psChild;
     706              40 :     for(; psIter != NULL; psIter = psIter->psNext)
     707                 :     {
     708              39 :         if (psIter->eType == CXT_Element &&
     709                 :             EQUAL(psIter->pszValue, "TileMap"))
     710                 :         {
     711              39 :             const char* pszHref = CPLGetXMLValue(psIter, "href", NULL);
     712              39 :             const char* pszTitle = CPLGetXMLValue(psIter, "title", NULL);
     713              39 :             if (pszHref && pszTitle)
     714                 :             {
     715              39 :                 CPLString osHref(pszHref);
     716              39 :                 const char* pszDup100 = strstr(pszHref, "1.0.0/1.0.0/");
     717              39 :                 if (pszDup100)
     718                 :                 {
     719              39 :                     osHref.resize(pszDup100 - pszHref);
     720              39 :                     osHref += pszDup100 + strlen("1.0.0/");
     721                 :                 }
     722              39 :                 poDS->AddSubDataset(osHref, pszTitle);
     723                 :             }
     724                 :         }
     725                 :     }
     726                 : 
     727               1 :     return poDS;
     728                 : }
     729                 : 

Generated by: LCOV version 1.7