LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/vrt - ogrvrtdriver.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 84 93 90.3 %
Date: 2024-11-21 22:18:42 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements OGRVRTDriver class.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
       9             :  * Copyright (c) 2009-2014, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_port.h"
      15             : #include "ogr_vrt.h"
      16             : 
      17             : #include <cctype>
      18             : #include <cstddef>
      19             : #include <cstdio>
      20             : #include <cstring>
      21             : #include <limits>
      22             : #include <memory>
      23             : #include <vector>
      24             : 
      25             : #include "cpl_conv.h"
      26             : #include "cpl_error.h"
      27             : #include "cpl_minixml.h"
      28             : #include "cpl_string.h"
      29             : #include "cpl_vsi.h"
      30             : #include "gdal.h"
      31             : #include "gdal_priv.h"
      32             : 
      33             : /************************************************************************/
      34             : /*                           OGRVRTErrorHandler()                       */
      35             : /************************************************************************/
      36             : 
      37          68 : static void CPL_STDCALL OGRVRTErrorHandler(CPL_UNUSED CPLErr eErr,
      38             :                                            CPL_UNUSED CPLErrorNum nType,
      39             :                                            const char *pszMsg)
      40             : {
      41             :     std::vector<CPLString> *paosErrors =
      42          68 :         static_cast<std::vector<CPLString> *>(CPLGetErrorHandlerUserData());
      43          68 :     paosErrors->push_back(pszMsg);
      44          68 : }
      45             : 
      46             : /************************************************************************/
      47             : /*                         OGRVRTDriverIdentify()                       */
      48             : /************************************************************************/
      49             : 
      50       49612 : static int OGRVRTDriverIdentify(GDALOpenInfo *poOpenInfo)
      51             : {
      52       49612 :     if (!poOpenInfo->bStatOK)
      53             :     {
      54             :         // Are we being passed the XML definition directly?
      55             :         // Skip any leading spaces/blanks.
      56       43166 :         const char *pszTestXML = poOpenInfo->pszFilename;
      57       43197 :         while (*pszTestXML != '\0' &&
      58       42378 :                isspace(static_cast<unsigned char>(*pszTestXML)))
      59          31 :             pszTestXML++;
      60       43166 :         if (STARTS_WITH_CI(pszTestXML, "<OGRVRTDataSource>"))
      61             :         {
      62         108 :             return TRUE;
      63             :         }
      64       43058 :         return FALSE;
      65             :     }
      66             : 
      67       12142 :     return poOpenInfo->fpL != nullptr &&
      68        5696 :            strstr(reinterpret_cast<char *>(poOpenInfo->pabyHeader),
      69        6446 :                   "<OGRVRTDataSource") != nullptr;
      70             : }
      71             : 
      72             : /************************************************************************/
      73             : /*                                Open()                                */
      74             : /************************************************************************/
      75             : 
      76         403 : static GDALDataset *OGRVRTDriverOpen(GDALOpenInfo *poOpenInfo)
      77             : 
      78             : {
      79             : #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
      80         403 :     if (!OGRVRTDriverIdentify(poOpenInfo))
      81           0 :         return nullptr;
      82             : #endif
      83             : 
      84             :     // Are we being passed the XML definition directly?
      85             :     // Skip any leading spaces/blanks.
      86         403 :     const char *pszTestXML = poOpenInfo->pszFilename;
      87         414 :     while (*pszTestXML != '\0' &&
      88         414 :            isspace(static_cast<unsigned char>(*pszTestXML)))
      89          11 :         pszTestXML++;
      90             : 
      91         403 :     char *pszXML = nullptr;
      92         403 :     if (STARTS_WITH_CI(pszTestXML, "<OGRVRTDataSource>"))
      93             :     {
      94          54 :         pszXML = CPLStrdup(pszTestXML);
      95             :     }
      96             : 
      97             :     // Open file and check if it contains appropriate XML.
      98             :     else
      99             :     {
     100             : #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
     101             :         if (poOpenInfo->fpL == nullptr)
     102             :             return nullptr;
     103             : #endif
     104             :         VSIStatBufL sStatBuf;
     105         349 :         if (VSIStatL(poOpenInfo->pszFilename, &sStatBuf) != 0)
     106             :         {
     107           0 :             return nullptr;
     108             :         }
     109         349 :         if (sStatBuf.st_size > 10 * 1024 * 1024 &&
     110           0 :             !CPLTestBool(CPLGetConfigOption("OGR_VRT_FORCE_LOADING", "NO")))
     111             :         {
     112           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     113             :                      "Suscipicously long VRT file. If you really want to "
     114             :                      "open it, define OGR_VRT_FORCE_LOADING=YES as "
     115             :                      "configuration option");
     116           0 :             return nullptr;
     117             :         }
     118         698 :         if (static_cast<uint64_t>(sStatBuf.st_size) >
     119         349 :             std::numeric_limits<size_t>::max() - 1)
     120             :         {
     121           0 :             return nullptr;
     122             :         }
     123             : 
     124             :         // It is the right file, now load the full XML definition.
     125         349 :         const size_t nLen = static_cast<size_t>(sStatBuf.st_size);
     126             : 
     127         349 :         pszXML = static_cast<char *>(VSI_MALLOC_VERBOSE(nLen + 1));
     128         349 :         if (pszXML == nullptr)
     129           0 :             return nullptr;
     130             : 
     131         349 :         pszXML[nLen] = '\0';
     132         349 :         VSIFSeekL(poOpenInfo->fpL, 0, SEEK_SET);
     133         349 :         if (VSIFReadL(pszXML, 1, nLen, poOpenInfo->fpL) != nLen)
     134             :         {
     135           0 :             CPLFree(pszXML);
     136           0 :             return nullptr;
     137             :         }
     138         349 :         VSIFCloseL(poOpenInfo->fpL);
     139         349 :         poOpenInfo->fpL = nullptr;
     140             :     }
     141             : 
     142             :     // Parse the XML.
     143         403 :     CPLXMLNode *psTree = CPLParseXMLString(pszXML);
     144             : 
     145         403 :     if (psTree == nullptr)
     146             :     {
     147           1 :         CPLFree(pszXML);
     148           1 :         return nullptr;
     149             :     }
     150             : 
     151             :     // XML Validation.
     152         402 :     if (CPLTestBool(CPLGetConfigOption("GDAL_XML_VALIDATION", "YES")))
     153             :     {
     154         402 :         const char *pszXSD = CPLFindFile("gdal", "ogrvrt.xsd");
     155         402 :         if (pszXSD != nullptr)
     156             :         {
     157         804 :             std::vector<CPLString> aosErrors;
     158         402 :             CPLPushErrorHandlerEx(OGRVRTErrorHandler, &aosErrors);
     159         402 :             const int bRet = CPLValidateXML(pszXML, pszXSD, nullptr);
     160         402 :             CPLPopErrorHandler();
     161         402 :             if (!bRet)
     162             :             {
     163         110 :                 if (!aosErrors.empty() &&
     164          55 :                     strstr(aosErrors[0].c_str(), "missing libxml2 support") ==
     165             :                         nullptr)
     166             :                 {
     167         118 :                     for (size_t i = 0; i < aosErrors.size(); i++)
     168             :                     {
     169          63 :                         CPLError(CE_Warning, CPLE_AppDefined, "%s",
     170          63 :                                  aosErrors[i].c_str());
     171             :                     }
     172             :                 }
     173             :             }
     174         402 :             CPLErrorReset();
     175             :         }
     176             :     }
     177         402 :     CPLFree(pszXML);
     178             : 
     179             :     // Create a virtual datasource configured based on this XML input.
     180             :     OGRVRTDataSource *poDS = new OGRVRTDataSource(
     181         402 :         static_cast<GDALDriver *>(GDALGetDriverByName("OGR_VRT")));
     182             : 
     183             :     // psTree is owned by poDS.
     184         402 :     if (!poDS->Initialize(psTree, poOpenInfo->pszFilename,
     185         402 :                           poOpenInfo->eAccess == GA_Update))
     186             :     {
     187           1 :         delete poDS;
     188           1 :         return nullptr;
     189             :     }
     190             : 
     191         401 :     return poDS;
     192             : }
     193             : 
     194             : /************************************************************************/
     195             : /*                           RegisterOGRVRT()                           */
     196             : /************************************************************************/
     197             : 
     198        1595 : void RegisterOGRVRT()
     199             : 
     200             : {
     201        1595 :     if (GDALGetDriverByName("OGR_VRT") != nullptr)
     202         302 :         return;
     203             : 
     204        1293 :     GDALDriver *poDriver = new GDALDriver();
     205             : 
     206        1293 :     poDriver->SetDescription("OGR_VRT");
     207        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
     208        1293 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "VRT - Virtual Datasource");
     209        1293 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "vrt");
     210        1293 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/vrt.html");
     211        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     212        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES, "YES");
     213        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_READ, "YES");
     214        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIPLE_VECTOR_LAYERS, "YES");
     215        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_CURVE_GEOMETRIES, "YES");
     216        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_MEASURED_GEOMETRIES, "YES");
     217        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
     218        1293 :     poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
     219             : 
     220        1293 :     poDriver->SetMetadataItem(GDAL_DMD_CREATION_FIELD_DEFN_FLAGS,
     221             :                               "WidthPrecision Nullable Unique Default "
     222        1293 :                               "Comment AlternativeName");
     223             : 
     224        1293 :     poDriver->pfnOpen = OGRVRTDriverOpen;
     225        1293 :     poDriver->pfnIdentify = OGRVRTDriverIdentify;
     226             : 
     227        1293 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     228             : }

Generated by: LCOV version 1.14