LCOV - code coverage report
Current view: directory - frmts/wms - wmsmetadataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 375 125 33.3 %
Date: 2012-04-28 Functions: 18 10 55.6 %

       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               4 : GDALWMSMetaDataset::GDALWMSMetaDataset() : papszSubDatasets(NULL)
      39                 : {
      40               4 : }
      41                 : 
      42                 : /************************************************************************/
      43                 : /*                         ~GDALWMSMetaDataset()                        */
      44                 : /************************************************************************/
      45                 : 
      46               4 : GDALWMSMetaDataset::~GDALWMSMetaDataset()
      47                 : {
      48               4 :     CSLDestroy(papszSubDatasets);
      49               4 : }
      50                 : 
      51                 : /************************************************************************/
      52                 : /*                            AddSubDataset()                           */
      53                 : /************************************************************************/
      54                 : 
      55             184 : void GDALWMSMetaDataset::AddSubDataset(const char* pszName,
      56                 :                                        const char* pszDesc)
      57                 : {
      58                 :     char    szName[80];
      59             184 :     int     nCount = CSLCount(papszSubDatasets ) / 2;
      60                 : 
      61             184 :     sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
      62                 :     papszSubDatasets =
      63             184 :         CSLSetNameValue( papszSubDatasets, szName, pszName );
      64                 : 
      65             184 :     sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
      66                 :     papszSubDatasets =
      67             184 :         CSLSetNameValue( papszSubDatasets, szName, pszDesc);
      68             184 : }
      69                 : 
      70                 : /************************************************************************/
      71                 : /*                        DownloadGetCapabilities()                     */
      72                 : /************************************************************************/
      73                 : 
      74               2 : GDALDataset *GDALWMSMetaDataset::DownloadGetCapabilities(GDALOpenInfo *poOpenInfo)
      75                 : {
      76               2 :     const char* pszURL = poOpenInfo->pszFilename;
      77               2 :     if (EQUALN(pszURL, "WMS:", 4))
      78               2 :         pszURL += 4;
      79                 : 
      80               2 :     CPLString osFormat = CPLURLGetValue(pszURL, "FORMAT");
      81               2 :     CPLString osTransparent = CPLURLGetValue(pszURL, "TRANSPARENT");
      82               2 :     CPLString osVersion = CPLURLGetValue(pszURL, "VERSION");
      83                 : 
      84               2 :     if (osVersion.size() == 0)
      85               2 :         osVersion = "1.1.1";
      86                 : 
      87               2 :     CPLString osURL(pszURL);
      88               2 :     osURL = CPLURLAddKVP(osURL, "SERVICE", "WMS");
      89               2 :     osURL = CPLURLAddKVP(osURL, "VERSION", osVersion);
      90               2 :     osURL = CPLURLAddKVP(osURL, "REQUEST", "GetCapabilities");
      91                 :     /* Remove all other keywords */
      92               2 :     osURL = CPLURLAddKVP(osURL, "LAYERS", NULL);
      93               2 :     osURL = CPLURLAddKVP(osURL, "SRS", NULL);
      94               2 :     osURL = CPLURLAddKVP(osURL, "CRS", NULL);
      95               2 :     osURL = CPLURLAddKVP(osURL, "BBOX", NULL);
      96               2 :     osURL = CPLURLAddKVP(osURL, "FORMAT", NULL);
      97               2 :     osURL = CPLURLAddKVP(osURL, "TRANSPARENT", NULL);
      98               2 :     osURL = CPLURLAddKVP(osURL, "STYLES", NULL);
      99               2 :     osURL = CPLURLAddKVP(osURL, "WIDTH", NULL);
     100               2 :     osURL = CPLURLAddKVP(osURL, "HEIGHT", NULL);
     101                 : 
     102               2 :     CPLHTTPResult* psResult = CPLHTTPFetch( osURL, NULL );
     103               2 :     if (psResult == NULL)
     104                 :     {
     105               0 :         return NULL;
     106                 :     }
     107               2 :     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               2 :                  psResult->nStatus);
     113               2 :         CPLHTTPDestroyResult(psResult);
     114               2 :         return NULL;
     115                 :     }
     116               0 :     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               0 :     CPLXMLNode* psXML = CPLParseXMLString( (const char*) psResult->pabyData );
     125               0 :     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               0 :     GDALDataset* poRet = AnalyzeGetCapabilities(psXML, osFormat, osTransparent);
     134                 : 
     135               0 :     CPLHTTPDestroyResult(psResult);
     136               0 :     CPLDestroyXMLNode( psXML );
     137                 : 
     138               0 :     return poRet;
     139                 : }
     140                 : 
     141                 : 
     142                 : /************************************************************************/
     143                 : /*                         DownloadGetTileService()                     */
     144                 : /************************************************************************/
     145                 : 
     146               2 : GDALDataset *GDALWMSMetaDataset::DownloadGetTileService(GDALOpenInfo *poOpenInfo)
     147                 : {
     148               2 :     const char* pszURL = poOpenInfo->pszFilename;
     149               2 :     if (EQUALN(pszURL, "WMS:", 4))
     150               2 :         pszURL += 4;
     151                 : 
     152               2 :     CPLString osURL(pszURL);
     153               2 :     osURL = CPLURLAddKVP(osURL, "SERVICE", "WMS");
     154               2 :     osURL = CPLURLAddKVP(osURL, "REQUEST", "GetTileService");
     155                 :     /* Remove all other keywords */
     156               2 :     osURL = CPLURLAddKVP(osURL, "VERSION", NULL);
     157               2 :     osURL = CPLURLAddKVP(osURL, "LAYERS", NULL);
     158               2 :     osURL = CPLURLAddKVP(osURL, "SRS", NULL);
     159               2 :     osURL = CPLURLAddKVP(osURL, "CRS", NULL);
     160               2 :     osURL = CPLURLAddKVP(osURL, "BBOX", NULL);
     161               2 :     osURL = CPLURLAddKVP(osURL, "FORMAT", NULL);
     162               2 :     osURL = CPLURLAddKVP(osURL, "TRANSPARENT", NULL);
     163               2 :     osURL = CPLURLAddKVP(osURL, "STYLES", NULL);
     164               2 :     osURL = CPLURLAddKVP(osURL, "WIDTH", NULL);
     165               2 :     osURL = CPLURLAddKVP(osURL, "HEIGHT", NULL);
     166                 : 
     167               2 :     CPLHTTPResult* psResult = CPLHTTPFetch( osURL, NULL );
     168               2 :     if (psResult == NULL)
     169                 :     {
     170               0 :         return NULL;
     171                 :     }
     172               2 :     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               2 :     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               2 :     CPLXMLNode* psXML = CPLParseXMLString( (const char*) psResult->pabyData );
     190               2 :     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               2 :     GDALDataset* poRet = AnalyzeGetTileService(psXML);
     199                 : 
     200               2 :     CPLHTTPDestroyResult(psResult);
     201               2 :     CPLDestroyXMLNode( psXML );
     202                 : 
     203               2 :     return poRet;
     204                 : }
     205                 : /************************************************************************/
     206                 : /*                            GetMetadata()                             */
     207                 : /************************************************************************/
     208                 : 
     209               4 : char **GDALWMSMetaDataset::GetMetadata( const char *pszDomain )
     210                 : 
     211                 : {
     212               4 :     if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
     213               4 :         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               0 : void GDALWMSMetaDataset::AddWMSCSubDataset(WMSCTileSetDesc& oWMSCTileSetDesc,
     289                 :                                           const char* pszTitle,
     290                 :                                           CPLString osTransparent)
     291                 : {
     292               0 :     CPLString osSubdatasetName = "WMS:";
     293               0 :     osSubdatasetName += osGetURL;
     294               0 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "SERVICE", "WMS");
     295               0 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "VERSION", osVersion);
     296               0 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "REQUEST", "GetMap");
     297               0 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "LAYERS", oWMSCTileSetDesc.osLayers);
     298               0 :     if(VersionStringToInt(osVersion.c_str())>= VersionStringToInt("1.3.0"))
     299               0 :         osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "CRS", oWMSCTileSetDesc.osSRS);
     300                 :     else
     301               0 :         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               0 :                                        oWMSCTileSetDesc.osMaxY.c_str()));
     307                 : 
     308               0 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "FORMAT", oWMSCTileSetDesc.osFormat);
     309               0 :     if (osTransparent.size() != 0)
     310                 :         osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "TRANSPARENT",
     311               0 :                                         osTransparent);
     312               0 :     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               0 :                                     CPLSPrintf("%d", oWMSCTileSetDesc.nTileWidth));
     317                 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "OVERVIEWCOUNT",
     318               0 :                                     CPLSPrintf("%d", oWMSCTileSetDesc.nResolutions - 1));
     319                 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "MINRESOLUTION",
     320               0 :                                     CPLSPrintf("%.16f", oWMSCTileSetDesc.dfMinResolution));
     321               0 :     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "TILED", "true");
     322                 : 
     323               0 :     if (pszTitle)
     324                 :     {
     325               0 :         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               0 :             AddSubDataset(osSubdatasetName, pszTitle);
     340                 :         }
     341                 :     }
     342                 :     else
     343                 :     {
     344               0 :         AddSubDataset(osSubdatasetName, oWMSCTileSetDesc.osLayers);
     345               0 :     }
     346               0 : }
     347                 : 
     348                 : /************************************************************************/
     349                 : /*                             ExploreLayer()                           */
     350                 : /************************************************************************/
     351                 : 
     352               0 : 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               0 :     const char* pszName = CPLGetXMLValue(psXML, "Name", NULL);
     362               0 :     const char* pszTitle = CPLGetXMLValue(psXML, "Title", NULL);
     363               0 :     const char* pszAbstract = CPLGetXMLValue(psXML, "Abstract", NULL);
     364                 : 
     365               0 :     const char* pszSRSLocal = NULL;
     366               0 :     const char* pszMinXLocal = NULL;
     367               0 :     const char* pszMinYLocal = NULL;
     368               0 :     const char* pszMaxXLocal = NULL;
     369               0 :     const char* pszMaxYLocal = NULL;
     370                 : 
     371                 :     const char* pszSRSTagName =
     372               0 :         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               0 :     CPLXMLNode* psSRS = CPLGetXMLNode( psXML, "BoundingBox" );
     378               0 :     if (psSRS == NULL)
     379                 :     {
     380               0 :         psSRS = CPLGetXMLNode( psXML, "LatLonBoundingBox" );
     381               0 :         pszSRSLocal = CPLGetXMLValue(psXML, pszSRSTagName, NULL);
     382               0 :         if (pszSRSLocal == NULL)
     383               0 :             pszSRSLocal = "EPSG:4326";
     384                 :     }
     385                 :     else
     386               0 :         pszSRSLocal = CPLGetXMLValue(psSRS, pszSRSTagName, NULL);
     387                 : 
     388               0 :     if (pszSRSLocal != NULL && psSRS != NULL)
     389                 :     {
     390               0 :         pszMinXLocal = CPLGetXMLValue(psSRS, "minx", NULL);
     391               0 :         pszMinYLocal = CPLGetXMLValue(psSRS, "miny", NULL);
     392               0 :         pszMaxXLocal = CPLGetXMLValue(psSRS, "maxx", NULL);
     393               0 :         pszMaxYLocal = CPLGetXMLValue(psSRS, "maxy", NULL);
     394                 : 
     395               0 :         if (pszMinXLocal && pszMinYLocal && pszMaxXLocal && pszMaxYLocal)
     396                 :         {
     397               0 :             pszSRS = pszSRSLocal;
     398               0 :             pszMinX = pszMinXLocal;
     399               0 :             pszMinY = pszMinYLocal;
     400               0 :             pszMaxX = pszMaxXLocal;
     401               0 :             pszMaxY = pszMaxYLocal;
     402                 :         }
     403                 :     }
     404                 : 
     405               0 :     if (pszName != NULL && pszSRS && pszMinX && pszMinY && pszMaxX && pszMaxY)
     406                 :     {
     407               0 :         CPLString osLocalTransparent(osTransparent);
     408               0 :         if (osLocalTransparent.size() == 0)
     409                 :         {
     410               0 :             const char* pszOpaque = CPLGetXMLValue(psXML, "opaque", "0");
     411               0 :             if (EQUAL(pszOpaque, "1"))
     412               0 :                 osLocalTransparent = "FALSE";
     413                 :         }
     414                 : 
     415               0 :         WMSCKeyType oWMSCKey(pszName, pszSRS);
     416               0 :         std::map<WMSCKeyType, WMSCTileSetDesc>::iterator oIter = osMapWMSCTileSet.find(oWMSCKey);
     417               0 :         if (oIter != osMapWMSCTileSet.end())
     418                 :         {
     419               0 :             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               0 :         }
     427                 :     }
     428                 : 
     429               0 :     CPLXMLNode* psIter = psXML->psChild;
     430               0 :     for(; psIter != NULL; psIter = psIter->psNext)
     431                 :     {
     432               0 :         if (psIter->eType == CXT_Element)
     433                 :         {
     434               0 :             if (EQUAL(psIter->pszValue, "Layer"))
     435                 :                 ExploreLayer(psIter, osFormat, osTransparent,
     436               0 :                              pszSRS, pszMinX, pszMinY, pszMaxX, pszMaxY);
     437                 :         }
     438                 :     }
     439               0 : }
     440                 : 
     441                 : /************************************************************************/
     442                 : /*                         ParseWMSCTileSets()                          */
     443                 : /************************************************************************/
     444                 : 
     445               0 : void GDALWMSMetaDataset::ParseWMSCTileSets(CPLXMLNode* psXML)
     446                 : {
     447               0 :     CPLXMLNode* psIter = psXML->psChild;
     448               0 :     for(;psIter;psIter = psIter->psNext)
     449                 :     {
     450               0 :         if (psIter->eType == CXT_Element && EQUAL(psIter->pszValue, "TileSet"))
     451                 :         {
     452               0 :             const char* pszSRS = CPLGetXMLValue(psIter, "SRS", NULL);
     453               0 :             if (pszSRS == NULL)
     454               0 :                 continue;
     455                 : 
     456               0 :             CPLXMLNode* psBoundingBox = CPLGetXMLNode( psIter, "BoundingBox" );
     457               0 :             if (psBoundingBox == NULL)
     458               0 :                 continue;
     459                 : 
     460               0 :             const char* pszMinX = CPLGetXMLValue(psBoundingBox, "minx", NULL);
     461               0 :             const char* pszMinY = CPLGetXMLValue(psBoundingBox, "miny", NULL);
     462               0 :             const char* pszMaxX = CPLGetXMLValue(psBoundingBox, "maxx", NULL);
     463               0 :             const char* pszMaxY = CPLGetXMLValue(psBoundingBox, "maxy", NULL);
     464               0 :             if (pszMinX == NULL || pszMinY == NULL || pszMaxX == NULL || pszMaxY == NULL)
     465               0 :                 continue;
     466                 : 
     467               0 :             double dfMinX = CPLAtofM(pszMinX);
     468               0 :             double dfMinY = CPLAtofM(pszMinY);
     469               0 :             double dfMaxX = CPLAtofM(pszMaxX);
     470               0 :             double dfMaxY = CPLAtofM(pszMaxY);
     471               0 :             if (dfMaxY <= dfMinY || dfMaxX <= dfMinX)
     472               0 :                 continue;
     473                 : 
     474               0 :             const char* pszFormat = CPLGetXMLValue( psIter, "Format", NULL );
     475               0 :             if (pszFormat == NULL)
     476               0 :                 continue;
     477               0 :             if (strstr(pszFormat, "kml"))
     478               0 :                 continue;
     479                 : 
     480               0 :             const char* pszTileWidth = CPLGetXMLValue(psIter, "Width", NULL);
     481               0 :             const char* pszTileHeight = CPLGetXMLValue(psIter, "Height", NULL);
     482               0 :             if (pszTileWidth == NULL || pszTileHeight == NULL)
     483               0 :                 continue;
     484                 : 
     485               0 :             int nTileWidth = atoi(pszTileWidth);
     486               0 :             int nTileHeight = atoi(pszTileHeight);
     487               0 :             if (nTileWidth < 128 || nTileHeight < 128)
     488               0 :                 continue;
     489                 : 
     490               0 :             const char* pszLayers = CPLGetXMLValue(psIter, "Layers", NULL);
     491               0 :             if (pszLayers == NULL)
     492               0 :                 continue;
     493                 : 
     494               0 :             const char* pszResolutions = CPLGetXMLValue(psIter, "Resolutions", NULL);
     495               0 :             if (pszResolutions == NULL)
     496               0 :                 continue;
     497               0 :             char** papszTokens = CSLTokenizeStringComplex(pszResolutions, " ", 0, 0);
     498               0 :             double dfMinResolution = 0;
     499                 :             int i;
     500               0 :             for(i=0; papszTokens && papszTokens[i]; i++)
     501                 :             {
     502               0 :                 double dfResolution = CPLAtofM(papszTokens[i]);
     503               0 :                 if (i==0 || dfResolution < dfMinResolution)
     504               0 :                     dfMinResolution = dfResolution;
     505                 :             }
     506               0 :             CSLDestroy(papszTokens);
     507               0 :             int nResolutions = i;
     508               0 :             if (nResolutions == 0)
     509               0 :                 continue;
     510                 : 
     511               0 :             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               0 :             WMSCKeyType oWMSCKey(pszLayers, pszSRS);
     517               0 :             std::map<WMSCKeyType, WMSCTileSetDesc>::iterator oIter = osMapWMSCTileSet.find(oWMSCKey);
     518               0 :             if (oIter != osMapWMSCTileSet.end())
     519               0 :                 continue;
     520                 : 
     521               0 :             WMSCTileSetDesc oWMSCTileSet;
     522               0 :             oWMSCTileSet.osLayers = pszLayers;
     523               0 :             oWMSCTileSet.osSRS = pszSRS;
     524               0 :             oWMSCTileSet.osMinX = pszMinX;
     525               0 :             oWMSCTileSet.osMinY = pszMinY;
     526               0 :             oWMSCTileSet.osMaxX = pszMaxX;
     527               0 :             oWMSCTileSet.osMaxY = pszMaxY;
     528               0 :             oWMSCTileSet.dfMinX = dfMinX;
     529               0 :             oWMSCTileSet.dfMinY = dfMinY;
     530               0 :             oWMSCTileSet.dfMaxX = dfMaxX;
     531               0 :             oWMSCTileSet.dfMaxY = dfMaxY;
     532               0 :             oWMSCTileSet.nResolutions = nResolutions;
     533               0 :             oWMSCTileSet.dfMinResolution = dfMinResolution;
     534               0 :             oWMSCTileSet.osFormat = pszFormat;
     535               0 :             oWMSCTileSet.osStyle = pszStyles;
     536               0 :             oWMSCTileSet.nTileWidth = nTileWidth;
     537               0 :             oWMSCTileSet.nTileHeight = nTileHeight;
     538                 : 
     539               0 :             osMapWMSCTileSet[oWMSCKey] = oWMSCTileSet;
     540                 :         }
     541                 :     }
     542               0 : }
     543                 : 
     544                 : /************************************************************************/
     545                 : /*                        AnalyzeGetCapabilities()                      */
     546                 : /************************************************************************/
     547                 : 
     548               0 : GDALDataset* GDALWMSMetaDataset::AnalyzeGetCapabilities(CPLXMLNode* psXML,
     549                 :                                                           CPLString osFormat,
     550                 :                                                           CPLString osTransparent)
     551                 : {
     552               0 :     const char* pszEncoding = NULL;
     553               0 :     if (psXML->eType == CXT_Element && strcmp(psXML->pszValue, "?xml") == 0)
     554               0 :         pszEncoding = CPLGetXMLValue(psXML, "encoding", NULL);
     555                 : 
     556               0 :     CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=WMT_MS_Capabilities" );
     557               0 :     if (psRoot == NULL)
     558               0 :         psRoot = CPLGetXMLNode( psXML, "=WMS_Capabilities" );
     559               0 :     if (psRoot == NULL)
     560               0 :         return NULL;
     561               0 :     CPLXMLNode* psCapability = CPLGetXMLNode(psRoot, "Capability");
     562               0 :     if (psCapability == NULL)
     563               0 :         return NULL;
     564                 : 
     565                 :     CPLXMLNode* psOnlineResource = CPLGetXMLNode(psCapability,
     566               0 :                              "Request.GetMap.DCPType.HTTP.Get.OnlineResource");
     567               0 :     if (psOnlineResource == NULL)
     568               0 :         return NULL;
     569                 :     const char* pszGetURL =
     570               0 :         CPLGetXMLValue(psOnlineResource, "xlink:href", NULL);
     571               0 :     if (pszGetURL == NULL)
     572               0 :         return NULL;
     573                 : 
     574               0 :     CPLXMLNode* psLayer = CPLGetXMLNode(psCapability, "Layer");
     575               0 :     if (psLayer == NULL)
     576               0 :         return NULL;
     577                 : 
     578                 :     CPLXMLNode* psVendorSpecificCapabilities =
     579               0 :         CPLGetXMLNode(psCapability, "VendorSpecificCapabilities");
     580                 : 
     581               0 :     GDALWMSMetaDataset* poDS = new GDALWMSMetaDataset();
     582               0 :     const char* pszVersion = CPLGetXMLValue(psRoot, "version", NULL);
     583               0 :     if (pszVersion)
     584               0 :         poDS->osVersion = pszVersion;
     585                 :     else
     586               0 :         poDS->osVersion = "1.1.1";
     587               0 :     poDS->osGetURL = pszGetURL;
     588               0 :     poDS->osXMLEncoding = pszEncoding ? pszEncoding : "";
     589               0 :     if (psVendorSpecificCapabilities)
     590               0 :         poDS->ParseWMSCTileSets(psVendorSpecificCapabilities);
     591               0 :     poDS->ExploreLayer(psLayer, osFormat, osTransparent);
     592                 : 
     593               0 :     return poDS;
     594                 : }
     595                 : 
     596                 : /************************************************************************/
     597                 : /*                          AddTiledSubDataset()                        */
     598                 : /************************************************************************/
     599                 : 
     600             106 : void GDALWMSMetaDataset::AddTiledSubDataset(const char* pszTiledGroupName,
     601                 :                                             const char* pszTitle)
     602                 : {
     603             106 :     CPLString osSubdatasetName = "<GDAL_WMS><Service name=\"TiledWMS\"><ServerUrl>";
     604             106 :     osSubdatasetName += osGetURL;
     605             106 :     osSubdatasetName += "</ServerUrl><TiledGroupName>";
     606             106 :     osSubdatasetName += pszTiledGroupName;
     607             106 :     osSubdatasetName += "</TiledGroupName></Service></GDAL_WMS>";
     608                 : 
     609             106 :     if (pszTitle)
     610                 :     {
     611             106 :         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             106 :             AddSubDataset(osSubdatasetName, pszTitle);
     626                 :         }
     627                 :     }
     628                 :     else
     629                 :     {
     630               0 :         AddSubDataset(osSubdatasetName, pszTiledGroupName);
     631             106 :     }
     632             106 : }
     633                 : 
     634                 : /************************************************************************/
     635                 : /*                     AnalyzeGetTileServiceRecurse()                   */
     636                 : /************************************************************************/
     637                 : 
     638              10 : void GDALWMSMetaDataset::AnalyzeGetTileServiceRecurse(CPLXMLNode* psXML)
     639                 : {
     640              10 :     CPLXMLNode* psIter = psXML->psChild;
     641             152 :     for(; psIter != NULL; psIter = psIter->psNext)
     642                 :     {
     643             248 :         if (psIter->eType == CXT_Element &&
     644                 :             EQUAL(psIter->pszValue, "TiledGroup"))
     645                 :         {
     646             106 :             const char* pszName = CPLGetXMLValue(psIter, "Name", NULL);
     647             106 :             const char* pszTitle = CPLGetXMLValue(psIter, "Title", NULL);
     648             106 :             if (pszName)
     649             106 :                 AddTiledSubDataset(pszName, pszTitle);
     650                 :         }
     651              36 :         else if (psIter->eType == CXT_Element &&
     652                 :             EQUAL(psIter->pszValue, "TiledGroups"))
     653                 :         {
     654               8 :             AnalyzeGetTileServiceRecurse(psIter);
     655                 :         }
     656                 :     }
     657              10 : }
     658                 : 
     659                 : /************************************************************************/
     660                 : /*                        AnalyzeGetTileService()                       */
     661                 : /************************************************************************/
     662                 : 
     663               2 : GDALDataset* GDALWMSMetaDataset::AnalyzeGetTileService(CPLXMLNode* psXML)
     664                 : {
     665               2 :     const char* pszEncoding = NULL;
     666               2 :     if (psXML->eType == CXT_Element && strcmp(psXML->pszValue, "?xml") == 0)
     667               0 :         pszEncoding = CPLGetXMLValue(psXML, "encoding", NULL);
     668                 : 
     669               2 :     CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=WMS_Tile_Service" );
     670               2 :     if (psRoot == NULL)
     671               0 :         return NULL;
     672               2 :     CPLXMLNode* psTiledPatterns = CPLGetXMLNode(psRoot, "TiledPatterns");
     673               2 :     if (psTiledPatterns == NULL)
     674               0 :         return NULL;
     675                 : 
     676                 :     const char* pszURL = CPLGetXMLValue(psTiledPatterns,
     677               2 :                                         "OnlineResource.xlink:href", NULL);
     678               2 :     if (pszURL == NULL)
     679               0 :         return NULL;
     680                 : 
     681               2 :     GDALWMSMetaDataset* poDS = new GDALWMSMetaDataset();
     682               4 :     poDS->osGetURL = pszURL;
     683               2 :     poDS->osXMLEncoding = pszEncoding ? pszEncoding : "";
     684                 : 
     685               2 :     poDS->AnalyzeGetTileServiceRecurse(psTiledPatterns);
     686                 : 
     687               2 :     return poDS;
     688                 : }
     689                 : 
     690                 : /************************************************************************/
     691                 : /*                        AnalyzeTileMapService()                       */
     692                 : /************************************************************************/
     693                 : 
     694               2 : GDALDataset* GDALWMSMetaDataset::AnalyzeTileMapService(CPLXMLNode* psXML)
     695                 : {
     696               2 :     CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=TileMapService" );
     697               2 :     if (psRoot == NULL)
     698               0 :         return NULL;
     699               2 :     CPLXMLNode* psTileMaps = CPLGetXMLNode(psRoot, "TileMaps");
     700               2 :     if (psTileMaps == NULL)
     701               0 :         return NULL;
     702                 : 
     703               2 :     GDALWMSMetaDataset* poDS = new GDALWMSMetaDataset();
     704                 : 
     705               2 :     CPLXMLNode* psIter = psTileMaps->psChild;
     706              80 :     for(; psIter != NULL; psIter = psIter->psNext)
     707                 :     {
     708              78 :         if (psIter->eType == CXT_Element &&
     709                 :             EQUAL(psIter->pszValue, "TileMap"))
     710                 :         {
     711              78 :             const char* pszHref = CPLGetXMLValue(psIter, "href", NULL);
     712              78 :             const char* pszTitle = CPLGetXMLValue(psIter, "title", NULL);
     713              78 :             if (pszHref && pszTitle)
     714                 :             {
     715              78 :                 CPLString osHref(pszHref);
     716              78 :                 const char* pszDup100 = strstr(pszHref, "1.0.0/1.0.0/");
     717              78 :                 if (pszDup100)
     718                 :                 {
     719              78 :                     osHref.resize(pszDup100 - pszHref);
     720              78 :                     osHref += pszDup100 + strlen("1.0.0/");
     721                 :                 }
     722              78 :                 poDS->AddSubDataset(osHref, pszTitle);
     723                 :             }
     724                 :         }
     725                 :     }
     726                 : 
     727               2 :     return poDS;
     728                 : }
     729                 : 

Generated by: LCOV version 1.7