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  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  ****************************************************************************/
28 
29 #include "cpl_conv.h"
30 #include "cpl_multiproc.h"
31 #include "nasreaderp.h"
32 #include "ogr_nas.h"
33 
34 CPL_CVSID("$Id: ogrnasdriver.cpp 1761acd90777d5bcc49eddbc13c193098f0ed40b 2020-10-01 12:12:00 +0200 Even Rouault $")
35 
36 /************************************************************************/
37 /*                     OGRNASDriverIdentify()                           */
38 /************************************************************************/
39 
OGRNASDriverIdentify(GDALOpenInfo * poOpenInfo)40 static int OGRNASDriverIdentify( GDALOpenInfo* poOpenInfo )
41 
42 {
43     if( poOpenInfo->fpL == nullptr )
44         return FALSE;
45 
46 /* -------------------------------------------------------------------- */
47 /*      Check for a UTF-8 BOM and skip if found                         */
48 /*                                                                      */
49 /*      TODO: BOM is variable-length parameter and depends on encoding. */
50 /*            Add BOM detection for other encodings.                    */
51 /* -------------------------------------------------------------------- */
52 
53     // Used to skip to actual beginning of XML data
54     // const char* szPtr = (const char*)poOpenInfo->pabyHeader;
55     const char* szPtr = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
56 
57     if( ( (unsigned char)szPtr[0] == 0xEF )
58         && ( (unsigned char)szPtr[1] == 0xBB )
59         && ( (unsigned char)szPtr[2] == 0xBF) )
60     {
61         szPtr += 3;
62     }
63 
64 /* -------------------------------------------------------------------- */
65 /*      Here, we expect the opening chevrons of NAS tree root element   */
66 /* -------------------------------------------------------------------- */
67     if( szPtr[0] != '<' )
68         return FALSE;
69 
70     if( !poOpenInfo->TryToIngest(8192) )
71         return FALSE;
72     szPtr = (const char*)poOpenInfo->pabyHeader;
73 
74     if( strstr(szPtr,"opengis.net/gml") == nullptr )
75         return FALSE;
76 
77     char **papszIndicators = CSLTokenizeStringComplex(
78         CPLGetConfigOption(
79             "NAS_INDICATOR",
80             "NAS-Operationen;AAA-Fachschema;aaa.xsd;aaa-suite" ),
81         ";", 0, 0 );
82 
83     bool bFound = false;
84     for( int i = 0; papszIndicators[i] && !bFound; i++ )
85     {
86         bFound = strstr( szPtr, papszIndicators[i] ) != nullptr;
87     }
88 
89     CSLDestroy( papszIndicators );
90 
91     return bFound;
92 }
93 
94 /************************************************************************/
95 /*                                Open()                                */
96 /************************************************************************/
97 
OGRNASDriverOpen(GDALOpenInfo * poOpenInfo)98 static GDALDataset *OGRNASDriverOpen( GDALOpenInfo* poOpenInfo )
99 
100 {
101     if( poOpenInfo->eAccess == GA_Update ||
102         !OGRNASDriverIdentify(poOpenInfo) )
103         return nullptr;
104 
105     VSIFCloseL(poOpenInfo->fpL);
106     poOpenInfo->fpL = nullptr;
107 
108     OGRNASDataSource *poDS = new OGRNASDataSource();
109 
110     if( !poDS->Open( poOpenInfo->pszFilename )
111         || poDS->GetLayerCount() == 0 )
112     {
113         delete poDS;
114         return nullptr;
115     }
116 
117     return poDS;
118 }
119 
120 /************************************************************************/
121 /*                           RegisterOGRNAS()                           */
122 /************************************************************************/
123 
RegisterOGRNAS()124 void RegisterOGRNAS()
125 
126 {
127     if( GDALGetDriverByName( "NAS" ) != nullptr )
128         return;
129 
130     GDALDriver *poDriver = new GDALDriver();
131 
132     poDriver->SetDescription( "NAS" );
133     poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
134     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "NAS - ALKIS" );
135     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "xml" );
136     poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drivers/vector/nas.html" );
137     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
138 
139     poDriver->pfnOpen = OGRNASDriverOpen;
140     poDriver->pfnIdentify = OGRNASDriverIdentify;
141 
142     GetGDALDriverManager()->RegisterDriver( poDriver );
143 }
144