Coverage Report

Created: 2025-06-09 08:44

/src/gdal/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp
Line
Count
Source (jump to first uncovered line)
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
static int OGRNASDriverIdentify(GDALOpenInfo *poOpenInfo)
23
24
130k
{
25
130k
    if (poOpenInfo->fpL == nullptr)
26
47.5k
        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
82.4k
    const char *pszPtr = reinterpret_cast<const char *>(poOpenInfo->pabyHeader);
37
38
    // Skip UTF-8 BOM
39
82.4k
    if (poOpenInfo->nHeaderBytes > 3 &&
40
82.4k
        memcmp(poOpenInfo->pabyHeader, "\xEF\xBB\xBF", 3) == 0)
41
131
    {
42
131
        pszPtr += 3;
43
131
    }
44
45
    // Skip spaces
46
138k
    while (*pszPtr && std::isspace(static_cast<unsigned char>(*pszPtr)))
47
55.6k
        ++pszPtr;
48
49
    /* -------------------------------------------------------------------- */
50
    /*      Here, we expect the opening chevrons of NAS tree root element   */
51
    /* -------------------------------------------------------------------- */
52
82.4k
    if (pszPtr[0] != '<')
53
74.8k
        return FALSE;
54
55
7.62k
    if (poOpenInfo->IsSingleAllowedDriver("NAS"))
56
0
        return TRUE;
57
58
    // TryToIngest() invalidates above pszPtr
59
7.62k
    pszPtr = nullptr;
60
7.62k
    CPL_IGNORE_RET_VAL(pszPtr);
61
7.62k
    if (!poOpenInfo->TryToIngest(8192))
62
0
        return FALSE;
63
7.62k
    pszPtr = reinterpret_cast<const char *>(poOpenInfo->pabyHeader);
64
65
7.62k
    if (strstr(pszPtr, "opengis.net/gml") == nullptr)
66
4.61k
        return FALSE;
67
68
3.01k
    char **papszIndicators = CSLTokenizeStringComplex(
69
3.01k
        CPLGetConfigOption("NAS_INDICATOR",
70
3.01k
                           "NAS-Operationen;AAA-Fachschema;aaa.xsd;aaa-suite"),
71
3.01k
        ";", 0, 0);
72
73
3.01k
    bool bFound = false;
74
12.0k
    for (int i = 0; papszIndicators[i] && !bFound; i++)
75
9.02k
    {
76
9.02k
        bFound = strstr(pszPtr, papszIndicators[i]) != nullptr;
77
9.02k
    }
78
79
3.01k
    CSLDestroy(papszIndicators);
80
81
    // Require NAS_GFS_TEMPLATE to be defined
82
3.01k
    if (bFound && !CPLGetConfigOption("NAS_GFS_TEMPLATE", nullptr))
83
1.20k
    {
84
1.20k
        CPLDebug("NAS",
85
1.20k
                 "This file could be recognized by the NAS driver. "
86
1.20k
                 "If this is desired, you need to define the NAS_GFS_TEMPLATE "
87
1.20k
                 "configuration option.");
88
1.20k
        return FALSE;
89
1.20k
    }
90
91
1.80k
    return bFound;
92
3.01k
}
93
94
/************************************************************************/
95
/*                                Open()                                */
96
/************************************************************************/
97
98
static GDALDataset *OGRNASDriverOpen(GDALOpenInfo *poOpenInfo)
99
100
0
{
101
0
    if (poOpenInfo->eAccess == GA_Update || !OGRNASDriverIdentify(poOpenInfo))
102
0
        return nullptr;
103
104
0
    VSIFCloseL(poOpenInfo->fpL);
105
0
    poOpenInfo->fpL = nullptr;
106
107
0
    OGRNASDataSource *poDS = new OGRNASDataSource();
108
109
0
    if (!poDS->Open(poOpenInfo->pszFilename))
110
0
    {
111
0
        delete poDS;
112
0
        return nullptr;
113
0
    }
114
115
0
    return poDS;
116
0
}
117
118
/************************************************************************/
119
/*                           RegisterOGRNAS()                           */
120
/************************************************************************/
121
122
void RegisterOGRNAS()
123
124
24
{
125
24
    if (GDALGetDriverByName("NAS") != nullptr)
126
0
        return;
127
128
24
    GDALDriver *poDriver = new GDALDriver();
129
130
24
    poDriver->SetDescription("NAS");
131
24
    poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
132
24
    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "NAS - ALKIS");
133
24
    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "xml");
134
24
    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/nas.html");
135
24
    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
136
24
    poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
137
138
24
    poDriver->pfnOpen = OGRNASDriverOpen;
139
24
    poDriver->pfnIdentify = OGRNASDriverIdentify;
140
141
24
    GetGDALDriverManager()->RegisterDriver(poDriver);
142
24
}