Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: WFS Translator 4 : * Purpose: Implements OGRWFSDriver. 5 : * Author: Even Rouault, even dot rouault at spatialys.com 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2010, Even Rouault <even dot rouault at spatialys.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "ogr_wfs.h" 14 : #include "cpl_conv.h" 15 : 16 : // g++ -fPIC -g -Wall ogr/ogrsf_frmts/wfs/*.cpp -shared -o ogr_WFS.so -Iport 17 : // -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/gml -Iogr/ogrsf_frmts/wfs 18 : // -L. -lgdal 19 : 20 : extern "C" void RegisterOGRWFS(); 21 : 22 : /************************************************************************/ 23 : /* Identify() */ 24 : /************************************************************************/ 25 : 26 45548 : static int OGRWFSDriverIdentify(GDALOpenInfo *poOpenInfo) 27 : 28 : { 29 45548 : if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "WFS:")) 30 : { 31 45286 : const bool bIsSingleDriver = poOpenInfo->IsSingleAllowedDriver("WFS"); 32 45286 : if (bIsSingleDriver && 33 2 : (STARTS_WITH(poOpenInfo->pszFilename, "http://") || 34 0 : STARTS_WITH(poOpenInfo->pszFilename, "https://"))) 35 : { 36 2 : return true; 37 : } 38 : 39 45284 : if (poOpenInfo->fpL == nullptr) 40 42717 : return FALSE; 41 : 42 2567 : const char *pszHeader = 43 : reinterpret_cast<const char *>(poOpenInfo->pabyHeader); 44 2567 : if (!STARTS_WITH_CI(pszHeader, "<OGRWFSDataSource>") && 45 2555 : strstr(pszHeader, "<WFS_Capabilities") == nullptr && 46 2547 : strstr(pszHeader, "<wfs:WFS_Capabilities") == nullptr) 47 : { 48 2547 : if (bIsSingleDriver) 49 : { 50 0 : while (*pszHeader != 0 && 51 0 : std::isspace(static_cast<unsigned char>(*pszHeader))) 52 0 : ++pszHeader; 53 0 : return *pszHeader == '<'; 54 : } 55 : 56 2547 : return FALSE; 57 : } 58 : } 59 282 : return TRUE; 60 : } 61 : 62 : /************************************************************************/ 63 : /* Open() */ 64 : /************************************************************************/ 65 : 66 142 : static GDALDataset *OGRWFSDriverOpen(GDALOpenInfo *poOpenInfo) 67 : 68 : { 69 142 : if (!OGRWFSDriverIdentify(poOpenInfo)) 70 0 : return nullptr; 71 : 72 142 : OGRWFSDataSource *poDS = new OGRWFSDataSource(); 73 : 74 142 : if (!poDS->Open(poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update, 75 142 : poOpenInfo->papszOpenOptions)) 76 : { 77 11 : delete poDS; 78 11 : poDS = nullptr; 79 : } 80 : 81 142 : return poDS; 82 : } 83 : 84 : /************************************************************************/ 85 : /* RegisterOGRWFS() */ 86 : /************************************************************************/ 87 : 88 1595 : void RegisterOGRWFS() 89 : 90 : { 91 1595 : if (GDALGetDriverByName("WFS") != nullptr) 92 302 : return; 93 : 94 1293 : GDALDriver *poDriver = new GDALDriver(); 95 : 96 1293 : poDriver->SetDescription("WFS"); 97 1293 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); 98 1293 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, 99 1293 : "OGC WFS (Web Feature Service)"); 100 1293 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/wfs.html"); 101 : 102 1293 : poDriver->SetMetadataItem(GDAL_DMD_CONNECTION_PREFIX, "WFS:"); 103 : 104 1293 : poDriver->SetMetadataItem( 105 : GDAL_DMD_OPENOPTIONLIST, 106 : "<OpenOptionList>" 107 : " <Option name='URL' type='string' description='URL to the WFS server " 108 : "endpoint' required='true'/>" 109 : " <Option name='TRUST_CAPABILITIES_BOUNDS' type='boolean' " 110 : "description='Whether to trust layer bounds declared in " 111 : "GetCapabilities response' default='NO'/>" 112 : " <Option name='EMPTY_AS_NULL' type='boolean' description='Force " 113 : "empty fields to be reported as NULL. Set to NO so that not-nullable " 114 : "fields can be exposed' default='YES'/>" 115 : " <Option name='INVERT_AXIS_ORDER_IF_LAT_LONG' type='boolean' " 116 : "description='Whether to present SRS and coordinate ordering in " 117 : "traditional GIS order' default='YES'/>" 118 : " <Option name='CONSIDER_EPSG_AS_URN' type='string-select' " 119 : "description='Whether to consider srsName like EPSG:XXXX as respecting " 120 : "EPSG axis order' default='AUTO'>" 121 : " <Value>AUTO</Value>" 122 : " <Value>YES</Value>" 123 : " <Value>NO</Value>" 124 : " </Option>" 125 : " <Option name='EXPOSE_GML_ID' type='boolean' description='Whether to " 126 : "make feature gml:id as a gml_id attribute.' default='YES'/>" 127 1293 : "</OpenOptionList>"); 128 : 129 1293 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); 130 1293 : poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE"); 131 : 132 1293 : poDriver->pfnIdentify = OGRWFSDriverIdentify; 133 1293 : poDriver->pfnOpen = OGRWFSDriverOpen; 134 : 135 1293 : GetGDALDriverManager()->RegisterDriver(poDriver); 136 : }