Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: OGR 4 : * Purpose: OGRNASDriver implementation 5 : * Author: Frank Warmerdam, warmerdam@pobox.com 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "cpl_conv.h" 14 : #include "cpl_multiproc.h" 15 : #include "nasreaderp.h" 16 : #include "ogr_nas.h" 17 : 18 : /************************************************************************/ 19 : /* OGRNASDriverIdentify() */ 20 : /************************************************************************/ 21 : 22 48336 : static int OGRNASDriverIdentify(GDALOpenInfo *poOpenInfo) 23 : 24 : { 25 48336 : if (poOpenInfo->fpL == nullptr) 26 43722 : return FALSE; 27 : 28 : /* -------------------------------------------------------------------- */ 29 : /* Check for a UTF-8 BOM and skip if found */ 30 : /* */ 31 : /* TODO: BOM is variable-length parameter and depends on encoding. */ 32 : /* Add BOM detection for other encodings. */ 33 : /* -------------------------------------------------------------------- */ 34 : 35 : // Used to skip to actual beginning of XML data 36 4614 : const char *pszPtr = reinterpret_cast<const char *>(poOpenInfo->pabyHeader); 37 : 38 : // Skip UTF-8 BOM 39 4614 : if (poOpenInfo->nHeaderBytes > 3 && 40 4521 : memcmp(poOpenInfo->pabyHeader, "\xEF\xBB\xBF", 3) == 0) 41 : { 42 8 : pszPtr += 3; 43 : } 44 : 45 : // Skip spaces 46 4868 : while (*pszPtr && std::isspace(static_cast<unsigned char>(*pszPtr))) 47 254 : ++pszPtr; 48 : 49 : /* -------------------------------------------------------------------- */ 50 : /* Here, we expect the opening chevrons of NAS tree root element */ 51 : /* -------------------------------------------------------------------- */ 52 4614 : if (pszPtr[0] != '<') 53 3872 : return FALSE; 54 : 55 742 : if (poOpenInfo->IsSingleAllowedDriver("NAS")) 56 2 : return TRUE; 57 : 58 : // TryToIngest() invalidates above pszPtr 59 740 : pszPtr = nullptr; 60 740 : CPL_IGNORE_RET_VAL(pszPtr); 61 740 : if (!poOpenInfo->TryToIngest(8192)) 62 0 : return FALSE; 63 740 : pszPtr = reinterpret_cast<const char *>(poOpenInfo->pabyHeader); 64 : 65 740 : if (strstr(pszPtr, "opengis.net/gml") == nullptr) 66 321 : return FALSE; 67 : 68 419 : char **papszIndicators = CSLTokenizeStringComplex( 69 : CPLGetConfigOption("NAS_INDICATOR", 70 : "NAS-Operationen;AAA-Fachschema;aaa.xsd;aaa-suite"), 71 : ";", 0, 0); 72 : 73 419 : bool bFound = false; 74 2071 : for (int i = 0; papszIndicators[i] && !bFound; i++) 75 : { 76 1652 : bFound = strstr(pszPtr, papszIndicators[i]) != nullptr; 77 : } 78 : 79 419 : CSLDestroy(papszIndicators); 80 : 81 : // Require NAS_GFS_TEMPLATE to be defined 82 419 : if (bFound && !CPLGetConfigOption("NAS_GFS_TEMPLATE", nullptr)) 83 : { 84 0 : CPLDebug("NAS", 85 : "This file could be recognized by the NAS driver. " 86 : "If this is desired, you need to define the NAS_GFS_TEMPLATE " 87 : "configuration option."); 88 0 : return FALSE; 89 : } 90 : 91 419 : return bFound; 92 : } 93 : 94 : /************************************************************************/ 95 : /* Open() */ 96 : /************************************************************************/ 97 : 98 5 : static GDALDataset *OGRNASDriverOpen(GDALOpenInfo *poOpenInfo) 99 : 100 : { 101 5 : if (poOpenInfo->eAccess == GA_Update || !OGRNASDriverIdentify(poOpenInfo)) 102 0 : return nullptr; 103 : 104 5 : VSIFCloseL(poOpenInfo->fpL); 105 5 : poOpenInfo->fpL = nullptr; 106 : 107 5 : OGRNASDataSource *poDS = new OGRNASDataSource(); 108 : 109 5 : if (!poDS->Open(poOpenInfo->pszFilename)) 110 : { 111 1 : delete poDS; 112 1 : return nullptr; 113 : } 114 : 115 4 : return poDS; 116 : } 117 : 118 : /************************************************************************/ 119 : /* RegisterOGRNAS() */ 120 : /************************************************************************/ 121 : 122 1595 : void RegisterOGRNAS() 123 : 124 : { 125 1595 : if (GDALGetDriverByName("NAS") != nullptr) 126 302 : return; 127 : 128 1293 : GDALDriver *poDriver = new GDALDriver(); 129 : 130 1293 : poDriver->SetDescription("NAS"); 131 1293 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); 132 1293 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "NAS - ALKIS"); 133 1293 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "xml"); 134 1293 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/nas.html"); 135 1293 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); 136 1293 : poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE"); 137 : 138 1293 : poDriver->pfnOpen = OGRNASDriverOpen; 139 1293 : poDriver->pfnIdentify = OGRNASDriverIdentify; 140 : 141 1293 : GetGDALDriverManager()->RegisterDriver(poDriver); 142 : }