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

Generated by: LCOV version 1.14