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

Generated by: LCOV version 1.14