LCOV - code coverage report
Current view: top level - frmts/nitf - nitfdrivercore.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 100 105 95.2 %
Date: 2025-10-17 14:31:27 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  NITF Read/Write Translator
       4             :  * Purpose:  NITFDataset and driver related implementations.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2002, Frank Warmerdam
       9             :  * Copyright (c) 2007-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * Portions Copyright (c) Her majesty the Queen in right of Canada as
      12             :  * represented by the Minister of National Defence, 2006.
      13             :  *
      14             :  * SPDX-License-Identifier: MIT
      15             :  ****************************************************************************/
      16             : 
      17             : #include "gdal_priv.h"
      18             : #include "gdal_frmts.h"
      19             : #include "gdalplugindriverproxy.h"
      20             : 
      21             : #include "nitfdrivercore.h"
      22             : 
      23             : /************************************************************************/
      24             : /*                     NITFDriverIdentify()                             */
      25             : /************************************************************************/
      26             : 
      27       65933 : int NITFDriverIdentify(GDALOpenInfo *poOpenInfo)
      28             : 
      29             : {
      30       65933 :     const char *pszFilename = poOpenInfo->pszFilename;
      31             : 
      32             :     /* -------------------------------------------------------------------- */
      33             :     /*      Is this a dataset selector? If so, it is obviously NITF.        */
      34             :     /* -------------------------------------------------------------------- */
      35       65933 :     if (STARTS_WITH_CI(pszFilename, "NITF_IM:"))
      36          40 :         return TRUE;
      37             : 
      38             :     /* -------------------------------------------------------------------- */
      39             :     /*      Avoid that on Windows, JPEG_SUBFILE:x,y,z,data/../tmp/foo.ntf   */
      40             :     /*      to be recognized by the NITF driver, because                    */
      41             :     /*      'JPEG_SUBFILE:x,y,z,data' is considered as a (valid) directory  */
      42             :     /*      and thus the whole filename is evaluated as tmp/foo.ntf         */
      43             :     /* -------------------------------------------------------------------- */
      44       65893 :     if (STARTS_WITH_CI(pszFilename, "JPEG_SUBFILE:"))
      45         146 :         return FALSE;
      46             : 
      47             :     /* -------------------------------------------------------------------- */
      48             :     /*      First we check to see if the file has the expected header       */
      49             :     /*      bytes.                                                          */
      50             :     /* -------------------------------------------------------------------- */
      51       65747 :     if (poOpenInfo->nHeaderBytes < 4)
      52       56338 :         return FALSE;
      53             : 
      54        9409 :     const char *pszHeader =
      55             :         reinterpret_cast<const char *>(poOpenInfo->pabyHeader);
      56        9409 :     if (!STARTS_WITH_CI(pszHeader, "NITF") &&
      57        8497 :         !STARTS_WITH_CI(pszHeader, "NSIF") &&
      58        8449 :         !STARTS_WITH_CI(pszHeader, "NITF"))
      59        8449 :         return FALSE;
      60             : 
      61             :     /* Check that it is not in fact a NITF A.TOC file, which is handled by the
      62             :      * RPFTOC driver */
      63      934096 :     for (int i = 0; i < static_cast<int>(poOpenInfo->nHeaderBytes) -
      64             :                             static_cast<int>(strlen("A.TOC"));
      65             :          i++)
      66             :     {
      67      933136 :         if (STARTS_WITH_CI(pszHeader + i, "A.TOC"))
      68           0 :             return FALSE;
      69             :     }
      70             : 
      71         960 :     return TRUE;
      72             : }
      73             : 
      74             : /************************************************************************/
      75             : /*                     NITFDriverSetCommonMetadata()                    */
      76             : /************************************************************************/
      77             : 
      78        1750 : void NITFDriverSetCommonMetadata(GDALDriver *poDriver)
      79             : {
      80        1750 :     poDriver->SetDescription(NITF_DRIVER_NAME);
      81        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
      82        1750 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
      83        1750 :                               "National Imagery Transmission Format");
      84             : 
      85        1750 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/nitf.html");
      86        1750 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "ntf");
      87        1750 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
      88        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_SUBDATASETS, "YES");
      89        1750 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
      90        1750 :                               "Byte UInt16 Int16 UInt32 Int32 Float32");
      91             : 
      92        1750 :     poDriver->SetMetadataItem(
      93             :         GDAL_DMD_OPENOPTIONLIST,
      94             :         "<OpenOptionList>"
      95             :         "  <Option name='VALIDATE' type='boolean' description='Whether "
      96             :         "validation of metadata should be done' default='NO' />"
      97             :         "  <Option name='FAIL_IF_VALIDATION_ERROR' type='boolean' "
      98             :         "description='Whether a validation error should cause dataset opening "
      99             :         "to fail' default='NO' />"
     100        1750 :         "</OpenOptionList>");
     101             : 
     102        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     103             : 
     104        1750 :     poDriver->pfnIdentify = NITFDriverIdentify;
     105        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     106        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
     107        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
     108             : 
     109        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_UPDATE, "YES");
     110        1750 :     poDriver->SetMetadataItem(GDAL_DMD_UPDATE_ITEMS, "RasterValues");
     111        1750 : }
     112             : 
     113             : /************************************************************************/
     114             : /*                     RPFTOCDriverIdentify()                           */
     115             : /************************************************************************/
     116             : 
     117       64834 : int RPFTOCDriverIdentify(GDALOpenInfo *poOpenInfo)
     118             : 
     119             : {
     120       64834 :     const char *pszFilename = poOpenInfo->pszFilename;
     121             : 
     122             :     /* -------------------------------------------------------------------- */
     123             :     /*      Is this a sub-dataset selector? If so, it is obviously RPFTOC.  */
     124             :     /* -------------------------------------------------------------------- */
     125             : 
     126       64834 :     if (STARTS_WITH_CI(pszFilename, "NITF_TOC_ENTRY:"))
     127          14 :         return TRUE;
     128             : 
     129             :     /* -------------------------------------------------------------------- */
     130             :     /*      First we check to see if the file has the expected header       */
     131             :     /*      bytes.                                                          */
     132             :     /* -------------------------------------------------------------------- */
     133       64820 :     if (poOpenInfo->nHeaderBytes < 48)
     134       56552 :         return FALSE;
     135             : 
     136        8268 :     if (RPFTOCIsNonNITFFileTOC(poOpenInfo, pszFilename))
     137           6 :         return TRUE;
     138             : 
     139        8262 :     const char *pszHeader =
     140             :         reinterpret_cast<const char *>(poOpenInfo->pabyHeader);
     141        8262 :     if (!STARTS_WITH_CI(pszHeader, "NITF") &&
     142        8258 :         !STARTS_WITH_CI(pszHeader, "NSIF") &&
     143        8257 :         !STARTS_WITH_CI(pszHeader, "NITF"))
     144        8257 :         return FALSE;
     145             : 
     146             :     /* If it is a NITF A.TOC file, it must contain A.TOC in its header */
     147        4846 :     for (int i = 0; i < static_cast<int>(poOpenInfo->nHeaderBytes) -
     148             :                             static_cast<int>(strlen("A.TOC"));
     149             :          i++)
     150             :     {
     151        4841 :         if (STARTS_WITH_CI(pszHeader + i, "A.TOC"))
     152           0 :             return TRUE;
     153             :     }
     154             : 
     155           5 :     return FALSE;
     156             : }
     157             : 
     158             : /************************************************************************/
     159             : /*                          IsNonNITFFileTOC()                          */
     160             : /************************************************************************/
     161             : 
     162             : /* Check whether the file is a TOC file without NITF header */
     163        8278 : int RPFTOCIsNonNITFFileTOC(GDALOpenInfo *poOpenInfo, const char *pszFilename)
     164             : {
     165        8278 :     const char pattern[] = {0,   0,   '0', ' ', ' ', ' ', ' ', ' ',
     166             :                             ' ', ' ', 'A', '.', 'T', 'O', 'C'};
     167        8278 :     if (poOpenInfo)
     168             :     {
     169        8271 :         if (poOpenInfo->nHeaderBytes < 48)
     170           0 :             return FALSE;
     171        8271 :         return memcmp(pattern, poOpenInfo->pabyHeader, 15) == 0;
     172             :     }
     173             :     else
     174             :     {
     175           7 :         VSILFILE *fp = VSIFOpenL(pszFilename, "rb");
     176           7 :         if (fp == nullptr)
     177             :         {
     178           0 :             return FALSE;
     179             :         }
     180             : 
     181             :         char buffer[48];
     182          14 :         int ret = (VSIFReadL(buffer, 1, 48, fp) == 48) &&
     183           7 :                   memcmp(pattern, buffer, 15) == 0;
     184           7 :         CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
     185           7 :         return ret;
     186             :     }
     187             : }
     188             : 
     189             : /************************************************************************/
     190             : /*                     RPFTOCDriverSetCommonMetadata()                  */
     191             : /************************************************************************/
     192             : 
     193        1750 : void RPFTOCDriverSetCommonMetadata(GDALDriver *poDriver)
     194             : {
     195        1750 :     poDriver->SetDescription(RPFTOC_DRIVER_NAME);
     196        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     197        1750 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     198        1750 :                               "Raster Product Format TOC format");
     199        1750 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/rpftoc.html");
     200        1750 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "toc");
     201        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     202        1750 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
     203        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     204        1750 :     poDriver->pfnIdentify = RPFTOCDriverIdentify;
     205        1750 : }
     206             : 
     207             : /************************************************************************/
     208             : /*                     ECRGTOCDriverIdentify()                          */
     209             : /************************************************************************/
     210             : 
     211       64845 : int ECRGTOCDriverIdentify(GDALOpenInfo *poOpenInfo)
     212             : 
     213             : {
     214       64845 :     const char *pszFilename = poOpenInfo->pszFilename;
     215             : 
     216             :     /* -------------------------------------------------------------------- */
     217             :     /*      Is this a sub-dataset selector? If so, it is obviously ECRGTOC. */
     218             :     /* -------------------------------------------------------------------- */
     219       64845 :     if (STARTS_WITH_CI(pszFilename, "ECRG_TOC_ENTRY:"))
     220          40 :         return TRUE;
     221             : 
     222             :     /* -------------------------------------------------------------------- */
     223             :     /*  First we check to see if the file has the expected header           */
     224             :     /*  bytes.                                                              */
     225             :     /* -------------------------------------------------------------------- */
     226       64805 :     const char *pabyHeader =
     227             :         reinterpret_cast<const char *>(poOpenInfo->pabyHeader);
     228       64805 :     if (pabyHeader == nullptr)
     229       56130 :         return FALSE;
     230             : 
     231        8675 :     if (strstr(pabyHeader, "<Table_of_Contents") != nullptr &&
     232          14 :         strstr(pabyHeader, "<file_header ") != nullptr)
     233          14 :         return TRUE;
     234             : 
     235        8661 :     if (strstr(pabyHeader, "<!DOCTYPE Table_of_Contents [") != nullptr)
     236           0 :         return TRUE;
     237             : 
     238        8661 :     return FALSE;
     239             : }
     240             : 
     241             : /************************************************************************/
     242             : /*                     ECRGTOCDriverSetCommonMetadata()                 */
     243             : /************************************************************************/
     244             : 
     245        1750 : void ECRGTOCDriverSetCommonMetadata(GDALDriver *poDriver)
     246             : {
     247        1750 :     poDriver->SetDescription(ECRGTOC_DRIVER_NAME);
     248        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     249        1750 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "ECRG TOC format");
     250        1750 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
     251        1750 :                               "drivers/raster/ecrgtoc.html");
     252        1750 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "xml");
     253        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     254        1750 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
     255        1750 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     256        1750 :     poDriver->pfnIdentify = ECRGTOCDriverIdentify;
     257        1750 : }
     258             : 
     259             : /************************************************************************/
     260             : /*                    DeclareDeferredNITFPlugin()                       */
     261             : /************************************************************************/
     262             : 
     263             : #ifdef PLUGIN_FILENAME
     264             : void DeclareDeferredNITFPlugin()
     265             : {
     266             :     if (GDALGetDriverByName(NITF_DRIVER_NAME) != nullptr)
     267             :     {
     268             :         return;
     269             :     }
     270             : 
     271             :     {
     272             :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     273             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     274             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     275             :                                   PLUGIN_INSTALLATION_MESSAGE);
     276             : #endif
     277             :         NITFDriverSetCommonMetadata(poDriver);
     278             :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     279             :     }
     280             : 
     281             :     {
     282             :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     283             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     284             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     285             :                                   PLUGIN_INSTALLATION_MESSAGE);
     286             : #endif
     287             :         RPFTOCDriverSetCommonMetadata(poDriver);
     288             :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     289             :     }
     290             : 
     291             :     {
     292             :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     293             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     294             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     295             :                                   PLUGIN_INSTALLATION_MESSAGE);
     296             : #endif
     297             :         ECRGTOCDriverSetCommonMetadata(poDriver);
     298             :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     299             :     }
     300             : }
     301             : #endif

Generated by: LCOV version 1.14