LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/svg - ogrsvgdatasource.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 71 97 73.2 %
Date: 2024-05-04 12:52:34 Functions: 9 10 90.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  SVG Translator
       4             :  * Purpose:  Implements OGRSVGDataSource class
       5             :  * Author:   Even Rouault, even dot rouault at spatialys.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2011, Even Rouault <even dot rouault at spatialys.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 "ogr_svg.h"
      30             : #include "cpl_conv.h"
      31             : 
      32             : /************************************************************************/
      33             : /*                          OGRSVGDataSource()                          */
      34             : /************************************************************************/
      35             : 
      36           1 : OGRSVGDataSource::OGRSVGDataSource()
      37             :     : pszName(nullptr), papoLayers(nullptr), nLayers(0)
      38             : #ifdef HAVE_EXPAT
      39             :       ,
      40             :       eValidity(SVG_VALIDITY_UNKNOWN), bIsCloudmade(false),
      41           1 :       oCurrentParser(nullptr), nDataHandlerCounter(0)
      42             : #endif
      43             : {
      44           1 : }
      45             : 
      46             : /************************************************************************/
      47             : /*                         ~OGRSVGDataSource()                          */
      48             : /************************************************************************/
      49             : 
      50           2 : OGRSVGDataSource::~OGRSVGDataSource()
      51             : 
      52             : {
      53           4 :     for (int i = 0; i < nLayers; i++)
      54           3 :         delete papoLayers[i];
      55           1 :     CPLFree(papoLayers);
      56           1 :     CPLFree(pszName);
      57           2 : }
      58             : 
      59             : /************************************************************************/
      60             : /*                              GetLayer()                              */
      61             : /************************************************************************/
      62             : 
      63          12 : OGRLayer *OGRSVGDataSource::GetLayer(int iLayer)
      64             : 
      65             : {
      66          12 :     if (iLayer < 0 || iLayer >= nLayers)
      67           0 :         return nullptr;
      68             :     else
      69          12 :         return papoLayers[iLayer];
      70             : }
      71             : 
      72             : #ifdef HAVE_EXPAT
      73             : 
      74             : /************************************************************************/
      75             : /*                startElementValidateCbk()                             */
      76             : /************************************************************************/
      77             : 
      78           4 : void OGRSVGDataSource::startElementValidateCbk(const char *pszNameIn,
      79             :                                                const char **ppszAttr)
      80             : {
      81           4 :     if (eValidity == SVG_VALIDITY_UNKNOWN)
      82             :     {
      83           1 :         if (strcmp(pszNameIn, "svg") == 0)
      84             :         {
      85           1 :             eValidity = SVG_VALIDITY_VALID;
      86           2 :             for (int i = 0; ppszAttr[i] != nullptr; i += 2)
      87             :             {
      88           2 :                 if (strcmp(ppszAttr[i], "xmlns:cm") == 0 &&
      89           1 :                     strcmp(ppszAttr[i + 1], "http://cloudmade.com/") == 0)
      90             :                 {
      91           1 :                     bIsCloudmade = true;
      92           1 :                     break;
      93             :                 }
      94             :             }
      95             :         }
      96             :         else
      97             :         {
      98           0 :             eValidity = SVG_VALIDITY_INVALID;
      99             :         }
     100             :     }
     101           4 : }
     102             : 
     103             : /************************************************************************/
     104             : /*                      dataHandlerValidateCbk()                        */
     105             : /************************************************************************/
     106             : 
     107           8 : void OGRSVGDataSource::dataHandlerValidateCbk(CPL_UNUSED const char *data,
     108             :                                               CPL_UNUSED int nLen)
     109             : {
     110           8 :     nDataHandlerCounter++;
     111           8 :     if (nDataHandlerCounter >= PARSER_BUF_SIZE)
     112             :     {
     113           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     114             :                  "File probably corrupted (million laugh pattern)");
     115           0 :         XML_StopParser(oCurrentParser, XML_FALSE);
     116             :     }
     117           8 : }
     118             : 
     119           4 : static void XMLCALL startElementValidateCbk(void *pUserData,
     120             :                                             const char *pszName,
     121             :                                             const char **ppszAttr)
     122             : {
     123           4 :     OGRSVGDataSource *poDS = (OGRSVGDataSource *)pUserData;
     124           4 :     poDS->startElementValidateCbk(pszName, ppszAttr);
     125           4 : }
     126             : 
     127           8 : static void XMLCALL dataHandlerValidateCbk(void *pUserData, const char *data,
     128             :                                            int nLen)
     129             : {
     130           8 :     OGRSVGDataSource *poDS = (OGRSVGDataSource *)pUserData;
     131           8 :     poDS->dataHandlerValidateCbk(data, nLen);
     132           8 : }
     133             : #endif
     134             : 
     135             : /************************************************************************/
     136             : /*                                Open()                                */
     137             : /************************************************************************/
     138             : 
     139           1 : int OGRSVGDataSource::Open(const char *pszFilename)
     140             : 
     141             : {
     142             : #ifdef HAVE_EXPAT
     143           1 :     pszName = CPLStrdup(pszFilename);
     144             : 
     145             :     /* -------------------------------------------------------------------- */
     146             :     /*      Try to open the file.                                           */
     147             :     /* -------------------------------------------------------------------- */
     148           2 :     CPLString osFilename;  // keep in that scope
     149           1 :     if (EQUAL(CPLGetExtension(pszFilename), "svgz") &&
     150           0 :         strstr(pszFilename, "/vsigzip/") == nullptr)
     151             :     {
     152           0 :         osFilename = CPLString("/vsigzip/") + pszFilename;
     153           0 :         pszFilename = osFilename.c_str();
     154             :     }
     155             : 
     156           1 :     VSILFILE *fp = VSIFOpenL(pszFilename, "r");
     157           1 :     if (fp == nullptr)
     158           0 :         return FALSE;
     159             : 
     160           1 :     eValidity = SVG_VALIDITY_UNKNOWN;
     161             : 
     162           1 :     XML_Parser oParser = OGRCreateExpatXMLParser();
     163           1 :     oCurrentParser = oParser;
     164           1 :     XML_SetUserData(oParser, this);
     165           1 :     XML_SetElementHandler(oParser, ::startElementValidateCbk, nullptr);
     166           1 :     XML_SetCharacterDataHandler(oParser, ::dataHandlerValidateCbk);
     167             : 
     168           1 :     std::vector<char> aBuf(PARSER_BUF_SIZE);
     169           1 :     int nDone = 0;
     170           1 :     unsigned int nLen = 0;
     171           1 :     int nCount = 0;
     172             : 
     173             :     /* Begin to parse the file and look for the <svg> element */
     174             :     /* It *MUST* be the first element of an XML file */
     175             :     /* So once we have read the first element, we know if we can */
     176             :     /* handle the file or not with that driver */
     177           0 :     do
     178             :     {
     179           1 :         nDataHandlerCounter = 0;
     180           1 :         nLen = (unsigned int)VSIFReadL(aBuf.data(), 1, aBuf.size(), fp);
     181           1 :         nDone = VSIFEofL(fp);
     182           1 :         if (XML_Parse(oParser, aBuf.data(), nLen, nDone) == XML_STATUS_ERROR)
     183             :         {
     184           0 :             if (nLen <= PARSER_BUF_SIZE - 1)
     185           0 :                 aBuf[nLen] = 0;
     186             :             else
     187           0 :                 aBuf[PARSER_BUF_SIZE - 1] = 0;
     188           0 :             if (strstr(aBuf.data(), "<?xml") && strstr(aBuf.data(), "<svg"))
     189             :             {
     190           0 :                 CPLError(
     191             :                     CE_Failure, CPLE_AppDefined,
     192             :                     "XML parsing of SVG file failed : %s at line %d, column %d",
     193             :                     XML_ErrorString(XML_GetErrorCode(oParser)),
     194           0 :                     (int)XML_GetCurrentLineNumber(oParser),
     195           0 :                     (int)XML_GetCurrentColumnNumber(oParser));
     196             :             }
     197           0 :             eValidity = SVG_VALIDITY_INVALID;
     198           0 :             break;
     199             :         }
     200           1 :         if (eValidity == SVG_VALIDITY_INVALID)
     201             :         {
     202           0 :             break;
     203             :         }
     204           1 :         else if (eValidity == SVG_VALIDITY_VALID)
     205             :         {
     206           1 :             break;
     207             :         }
     208             :         else
     209             :         {
     210             :             /* After reading 50 * PARSER_BUF_SIZE bytes, and not finding whether the
     211             :              * file */
     212             :             /* is SVG or not, we give up and fail silently */
     213           0 :             nCount++;
     214           0 :             if (nCount == 50)
     215           0 :                 break;
     216             :         }
     217           0 :     } while (!nDone && nLen > 0);
     218             : 
     219           1 :     XML_ParserFree(oParser);
     220             : 
     221           1 :     VSIFCloseL(fp);
     222             : 
     223           1 :     if (eValidity == SVG_VALIDITY_VALID)
     224             :     {
     225           1 :         if (bIsCloudmade)
     226             :         {
     227           1 :             nLayers = 3;
     228           2 :             papoLayers = (OGRSVGLayer **)CPLRealloc(
     229           1 :                 papoLayers, nLayers * sizeof(OGRSVGLayer *));
     230           1 :             papoLayers[0] =
     231           1 :                 new OGRSVGLayer(pszFilename, "points", SVG_POINTS, this);
     232           1 :             papoLayers[1] =
     233           1 :                 new OGRSVGLayer(pszFilename, "lines", SVG_LINES, this);
     234           1 :             papoLayers[2] =
     235           1 :                 new OGRSVGLayer(pszFilename, "polygons", SVG_POLYGONS, this);
     236             :         }
     237             :         else
     238             :         {
     239           0 :             CPLDebug(
     240             :                 "SVG",
     241             :                 "%s seems to be a SVG file, but not a Cloudmade vector one.",
     242             :                 pszFilename);
     243             :         }
     244             :     }
     245             : 
     246           1 :     return nLayers > 0;
     247             : #else
     248             :     char aBuf[256];
     249             :     VSILFILE *fp = VSIFOpenL(pszFilename, "r");
     250             :     if (fp)
     251             :     {
     252             :         unsigned int nLen = (unsigned int)VSIFReadL(aBuf, 1, 255, fp);
     253             :         aBuf[nLen] = 0;
     254             :         if (strstr(aBuf, "<?xml") && strstr(aBuf, "<svg") &&
     255             :             strstr(aBuf, "http://cloudmade.com/"))
     256             :         {
     257             :             CPLError(CE_Failure, CPLE_NotSupported,
     258             :                      "OGR/SVG driver has not been built with read support. "
     259             :                      "Expat library required");
     260             :         }
     261             :         VSIFCloseL(fp);
     262             :     }
     263             :     return FALSE;
     264             : #endif
     265             : }
     266             : 
     267             : /************************************************************************/
     268             : /*                            TestCapability()                          */
     269             : /************************************************************************/
     270             : 
     271           0 : int OGRSVGDataSource::TestCapability(CPL_UNUSED const char *pszCap)
     272             : {
     273           0 :     return FALSE;
     274             : }

Generated by: LCOV version 1.14