LCOV - code coverage report
Current view: top level - frmts/nitf - nitfdrivercore.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 98 103 95.1 %
Date: 2025-05-11 14:50:45 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       59474 : int NITFDriverIdentify(GDALOpenInfo *poOpenInfo)
      24             : 
      25             : {
      26       59474 :     const char *pszFilename = poOpenInfo->pszFilename;
      27             : 
      28             :     /* -------------------------------------------------------------------- */
      29             :     /*      Is this a dataset selector? If so, it is obviously NITF.        */
      30             :     /* -------------------------------------------------------------------- */
      31       59474 :     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       59434 :     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       59284 :     if (poOpenInfo->nHeaderBytes < 4)
      48       49837 :         return FALSE;
      49             : 
      50        9447 :     if (!STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "NITF") &&
      51        8214 :         !STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "NSIF") &&
      52        8166 :         !STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "NITF"))
      53        8166 :         return FALSE;
      54             : 
      55             :     /* Check that it is not in fact a NITF A.TOC file, which is handled by the
      56             :      * RPFTOC driver */
      57     1221370 :     for (int i = 0; i < static_cast<int>(poOpenInfo->nHeaderBytes) -
      58             :                             static_cast<int>(strlen("A.TOC"));
      59             :          i++)
      60             :     {
      61     1220090 :         if (STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader + i, "A.TOC"))
      62           0 :             return FALSE;
      63             :     }
      64             : 
      65        1281 :     return TRUE;
      66             : }
      67             : 
      68             : /************************************************************************/
      69             : /*                     NITFDriverSetCommonMetadata()                    */
      70             : /************************************************************************/
      71             : 
      72        1390 : void NITFDriverSetCommonMetadata(GDALDriver *poDriver)
      73             : {
      74        1390 :     poDriver->SetDescription(NITF_DRIVER_NAME);
      75        1390 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
      76        1390 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
      77        1390 :                               "National Imagery Transmission Format");
      78             : 
      79        1390 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/nitf.html");
      80        1390 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "ntf");
      81        1390 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
      82        1390 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_SUBDATASETS, "YES");
      83        1390 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
      84        1390 :                               "Byte UInt16 Int16 UInt32 Int32 Float32");
      85             : 
      86        1390 :     poDriver->SetMetadataItem(
      87             :         GDAL_DMD_OPENOPTIONLIST,
      88             :         "<OpenOptionList>"
      89             :         "  <Option name='VALIDATE' type='boolean' description='Whether "
      90             :         "validation of metadata should be done' default='NO' />"
      91             :         "  <Option name='FAIL_IF_VALIDATION_ERROR' type='boolean' "
      92             :         "description='Whether a validation error should cause dataset opening "
      93             :         "to fail' default='NO' />"
      94        1390 :         "</OpenOptionList>");
      95             : 
      96        1390 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
      97             : 
      98        1390 :     poDriver->pfnIdentify = NITFDriverIdentify;
      99        1390 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     100        1390 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
     101        1390 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
     102             : 
     103        1390 :     poDriver->SetMetadataItem(GDAL_DCAP_UPDATE, "YES");
     104        1390 :     poDriver->SetMetadataItem(GDAL_DMD_UPDATE_ITEMS, "RasterValues");
     105        1390 : }
     106             : 
     107             : /************************************************************************/
     108             : /*                     RPFTOCDriverIdentify()                           */
     109             : /************************************************************************/
     110             : 
     111       58055 : int RPFTOCDriverIdentify(GDALOpenInfo *poOpenInfo)
     112             : 
     113             : {
     114       58055 :     const char *pszFilename = poOpenInfo->pszFilename;
     115             : 
     116             :     /* -------------------------------------------------------------------- */
     117             :     /*      Is this a sub-dataset selector? If so, it is obviously RPFTOC.  */
     118             :     /* -------------------------------------------------------------------- */
     119             : 
     120       58055 :     if (STARTS_WITH_CI(pszFilename, "NITF_TOC_ENTRY:"))
     121          14 :         return TRUE;
     122             : 
     123             :     /* -------------------------------------------------------------------- */
     124             :     /*      First we check to see if the file has the expected header       */
     125             :     /*      bytes.                                                          */
     126             :     /* -------------------------------------------------------------------- */
     127       58041 :     if (poOpenInfo->nHeaderBytes < 48)
     128       50046 :         return FALSE;
     129             : 
     130        7995 :     if (RPFTOCIsNonNITFFileTOC(poOpenInfo, pszFilename))
     131           6 :         return TRUE;
     132             : 
     133        7989 :     if (!STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "NITF") &&
     134        7985 :         !STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "NSIF") &&
     135        7984 :         !STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "NITF"))
     136        7984 :         return FALSE;
     137             : 
     138             :     /* If it is a NITF A.TOC file, it must contain A.TOC in its header */
     139        4846 :     for (int i = 0; i < static_cast<int>(poOpenInfo->nHeaderBytes) -
     140             :                             static_cast<int>(strlen("A.TOC"));
     141             :          i++)
     142             :     {
     143        4841 :         if (STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader + i, "A.TOC"))
     144           0 :             return TRUE;
     145             :     }
     146             : 
     147           5 :     return FALSE;
     148             : }
     149             : 
     150             : /************************************************************************/
     151             : /*                          IsNonNITFFileTOC()                          */
     152             : /************************************************************************/
     153             : 
     154             : /* Check whether the file is a TOC file without NITF header */
     155        8005 : int RPFTOCIsNonNITFFileTOC(GDALOpenInfo *poOpenInfo, const char *pszFilename)
     156             : {
     157        8005 :     const char pattern[] = {0,   0,   '0', ' ', ' ', ' ', ' ', ' ',
     158             :                             ' ', ' ', 'A', '.', 'T', 'O', 'C'};
     159        8005 :     if (poOpenInfo)
     160             :     {
     161        7998 :         if (poOpenInfo->nHeaderBytes < 48)
     162           0 :             return FALSE;
     163        7998 :         return memcmp(pattern, poOpenInfo->pabyHeader, 15) == 0;
     164             :     }
     165             :     else
     166             :     {
     167           7 :         VSILFILE *fp = VSIFOpenL(pszFilename, "rb");
     168           7 :         if (fp == nullptr)
     169             :         {
     170           0 :             return FALSE;
     171             :         }
     172             : 
     173             :         char buffer[48];
     174          14 :         int ret = (VSIFReadL(buffer, 1, 48, fp) == 48) &&
     175           7 :                   memcmp(pattern, buffer, 15) == 0;
     176           7 :         CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
     177           7 :         return ret;
     178             :     }
     179             : }
     180             : 
     181             : /************************************************************************/
     182             : /*                     RPFTOCDriverSetCommonMetadata()                  */
     183             : /************************************************************************/
     184             : 
     185        1390 : void RPFTOCDriverSetCommonMetadata(GDALDriver *poDriver)
     186             : {
     187        1390 :     poDriver->SetDescription(RPFTOC_DRIVER_NAME);
     188        1390 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     189        1390 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     190        1390 :                               "Raster Product Format TOC format");
     191        1390 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/rpftoc.html");
     192        1390 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "toc");
     193        1390 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     194        1390 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
     195        1390 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     196        1390 :     poDriver->pfnIdentify = RPFTOCDriverIdentify;
     197        1390 : }
     198             : 
     199             : /************************************************************************/
     200             : /*                     ECRGTOCDriverIdentify()                          */
     201             : /************************************************************************/
     202             : 
     203       58066 : int ECRGTOCDriverIdentify(GDALOpenInfo *poOpenInfo)
     204             : 
     205             : {
     206       58066 :     const char *pszFilename = poOpenInfo->pszFilename;
     207             : 
     208             :     /* -------------------------------------------------------------------- */
     209             :     /*      Is this a sub-dataset selector? If so, it is obviously ECRGTOC. */
     210             :     /* -------------------------------------------------------------------- */
     211       58066 :     if (STARTS_WITH_CI(pszFilename, "ECRG_TOC_ENTRY:"))
     212          40 :         return TRUE;
     213             : 
     214             :     /* -------------------------------------------------------------------- */
     215             :     /*  First we check to see if the file has the expected header           */
     216             :     /*  bytes.                                                              */
     217             :     /* -------------------------------------------------------------------- */
     218       58026 :     const char *pabyHeader =
     219             :         reinterpret_cast<const char *>(poOpenInfo->pabyHeader);
     220       58026 :     if (pabyHeader == nullptr)
     221       49646 :         return FALSE;
     222             : 
     223        8380 :     if (strstr(pabyHeader, "<Table_of_Contents") != nullptr &&
     224          14 :         strstr(pabyHeader, "<file_header ") != nullptr)
     225          14 :         return TRUE;
     226             : 
     227        8366 :     if (strstr(pabyHeader, "<!DOCTYPE Table_of_Contents [") != nullptr)
     228           0 :         return TRUE;
     229             : 
     230        8366 :     return FALSE;
     231             : }
     232             : 
     233             : /************************************************************************/
     234             : /*                     ECRGTOCDriverSetCommonMetadata()                 */
     235             : /************************************************************************/
     236             : 
     237        1390 : void ECRGTOCDriverSetCommonMetadata(GDALDriver *poDriver)
     238             : {
     239        1390 :     poDriver->SetDescription(ECRGTOC_DRIVER_NAME);
     240        1390 :     poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     241        1390 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "ECRG TOC format");
     242        1390 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
     243        1390 :                               "drivers/raster/ecrgtoc.html");
     244        1390 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "xml");
     245        1390 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     246        1390 :     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
     247        1390 :     poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
     248        1390 :     poDriver->pfnIdentify = ECRGTOCDriverIdentify;
     249        1390 : }
     250             : 
     251             : /************************************************************************/
     252             : /*                    DeclareDeferredNITFPlugin()                       */
     253             : /************************************************************************/
     254             : 
     255             : #ifdef PLUGIN_FILENAME
     256             : void DeclareDeferredNITFPlugin()
     257             : {
     258             :     if (GDALGetDriverByName(NITF_DRIVER_NAME) != nullptr)
     259             :     {
     260             :         return;
     261             :     }
     262             : 
     263             :     {
     264             :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     265             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     266             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     267             :                                   PLUGIN_INSTALLATION_MESSAGE);
     268             : #endif
     269             :         NITFDriverSetCommonMetadata(poDriver);
     270             :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     271             :     }
     272             : 
     273             :     {
     274             :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     275             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     276             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     277             :                                   PLUGIN_INSTALLATION_MESSAGE);
     278             : #endif
     279             :         RPFTOCDriverSetCommonMetadata(poDriver);
     280             :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     281             :     }
     282             : 
     283             :     {
     284             :         auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
     285             : #ifdef PLUGIN_INSTALLATION_MESSAGE
     286             :         poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
     287             :                                   PLUGIN_INSTALLATION_MESSAGE);
     288             : #endif
     289             :         ECRGTOCDriverSetCommonMetadata(poDriver);
     290             :         GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
     291             :     }
     292             : }
     293             : #endif

Generated by: LCOV version 1.14