LTP GCOV extension - code coverage report
Current view: directory - frmts/nitf - nitfdes.c
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 197
Code covered: 45.7 % Executed lines: 90

       1                 : /******************************************************************************
       2                 :  * $Id: nitfdes.c 19385 2010-04-11 18:05:19Z rouault $
       3                 :  *
       4                 :  * Project:  NITF Read/Write Library
       5                 :  * Purpose:  Module responsible for implementation of DE segments.
       6                 :  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
       7                 :  *
       8                 :  **********************************************************************
       9                 :  * Copyright (c) 2010, Even Rouault <even dot rouault at mines dash paris dot org>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "gdal.h"
      31                 : #include "nitflib.h"
      32                 : #include "cpl_vsi.h"
      33                 : #include "cpl_conv.h"
      34                 : #include "cpl_string.h"
      35                 : 
      36                 : CPL_CVSID("$Id: nitfdes.c 19385 2010-04-11 18:05:19Z rouault $");
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                          NITFDESAccess()                             */
      40                 : /************************************************************************/
      41                 : 
      42                 : NITFDES *NITFDESAccess( NITFFile *psFile, int iSegment )
      43                 : 
      44               1 : {
      45                 :     NITFDES   *psDES;
      46                 :     char      *pachHeader;
      47                 :     NITFSegmentInfo *psSegInfo;
      48                 :     char       szDESID[26];
      49                 :     char       szTemp[128];
      50                 :     int        nOffset;
      51                 :     int        bHasDESOFLW;
      52                 :     int        nDESSHL;
      53                 :     
      54                 : /* -------------------------------------------------------------------- */
      55                 : /*      Verify segment, and return existing DES accessor if there       */
      56                 : /*      is one.                                                         */
      57                 : /* -------------------------------------------------------------------- */
      58               1 :     if( iSegment < 0 || iSegment >= psFile->nSegmentCount )
      59               0 :         return NULL;
      60                 : 
      61               1 :     psSegInfo = psFile->pasSegmentInfo + iSegment;
      62                 : 
      63               1 :     if( !EQUAL(psSegInfo->szSegmentType,"DE") )
      64               0 :         return NULL;
      65                 : 
      66               1 :     if( psSegInfo->hAccess != NULL )
      67               0 :         return (NITFDES *) psSegInfo->hAccess;
      68                 : 
      69                 : /* -------------------------------------------------------------------- */
      70                 : /*      Read the DES subheader.                                         */
      71                 : /* -------------------------------------------------------------------- */
      72               1 :     if (psSegInfo->nSegmentHeaderSize < 200)
      73                 :     {
      74               0 :         CPLError(CE_Failure, CPLE_AppDefined,
      75                 :                     "DES header too small");
      76               0 :         return NULL;
      77                 :     }
      78                 : 
      79               1 :     pachHeader = (char*) VSIMalloc(psSegInfo->nSegmentHeaderSize);
      80               1 :     if (pachHeader == NULL)
      81                 :     {
      82               0 :         CPLError(CE_Failure, CPLE_OutOfMemory,
      83                 :                  "Cannot allocate memory for segment header");
      84               0 :         return NULL;
      85                 :     }
      86                 : 
      87               1 : retry:
      88               1 :     if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart, 
      89                 :                   SEEK_SET ) != 0 
      90                 :         || VSIFReadL( pachHeader, 1, psSegInfo->nSegmentHeaderSize, 
      91                 :                      psFile->fp ) != psSegInfo->nSegmentHeaderSize )
      92                 :     {
      93               0 :         CPLError( CE_Failure, CPLE_FileIO, 
      94                 :                   "Failed to read %u byte DES subheader from " CPL_FRMT_GUIB ".",
      95                 :                   psSegInfo->nSegmentHeaderSize,
      96                 :                   psSegInfo->nSegmentHeaderStart );
      97               0 :         CPLFree(pachHeader);
      98               0 :         return NULL;
      99                 :     }
     100                 : 
     101               1 :     if (!EQUALN(pachHeader, "DE", 2))
     102                 :     {
     103               0 :         if (EQUALN(pachHeader + 4, "DERegistered", 12))
     104                 :         {
     105                 :             /* BAO_46_Ed1/rpf/conc/concz10/000fz010.ona and cie are buggy */
     106               0 :             CPLDebug("NITF", "Patching nSegmentHeaderStart and nSegmentStart for DE segment %d", iSegment);
     107               0 :             psSegInfo->nSegmentHeaderStart += 4;
     108               0 :             psSegInfo->nSegmentStart += 4;
     109               0 :             goto retry;
     110                 :         }
     111                 : 
     112               0 :         CPLError(CE_Failure, CPLE_AppDefined,
     113                 :                  "Invalid segment prefix for DE segment %d", iSegment);
     114                 : 
     115               0 :         CPLFree(pachHeader);
     116               0 :         return NULL;
     117                 :     }
     118                 : 
     119                 : /* -------------------------------------------------------------------- */
     120                 : /*      Initialize DES object.                                          */
     121                 : /* -------------------------------------------------------------------- */
     122               1 :     psDES = (NITFDES *) CPLCalloc(sizeof(NITFDES),1);
     123                 : 
     124               1 :     psDES->psFile = psFile;
     125               1 :     psDES->iSegment = iSegment;
     126               1 :     psDES->pachHeader = pachHeader;
     127                 : 
     128               1 :     psSegInfo->hAccess = psDES;
     129                 : 
     130                 : /* -------------------------------------------------------------------- */
     131                 : /*      Collect a variety of information as metadata.                   */
     132                 : /* -------------------------------------------------------------------- */
     133                 : #define GetMD( length, name )              \
     134                 :     do { NITFExtractMetadata( &(psDES->papszMetadata), pachHeader,    \
     135                 :                          nOffset, length,                        \
     136                 :                          "NITF_" #name ); \
     137                 :     nOffset += length; } while(0)
     138                 : 
     139               1 :     nOffset = 2;
     140               1 :     GetMD( 25, DESID  );
     141               1 :     GetMD(  2, DESVER );
     142               1 :     GetMD(  1, DECLAS );
     143               1 :     GetMD(  2, DESCLSY );
     144               1 :     GetMD( 11, DESCODE );
     145               1 :     GetMD(  2, DESCTLH );
     146               1 :     GetMD( 20, DESREL  );
     147               1 :     GetMD(  2, DESDCTP );
     148               1 :     GetMD(  8, DESDCDT );
     149               1 :     GetMD(  4, DESDCXM );
     150               1 :     GetMD(  1, DESDG   );
     151               1 :     GetMD(  8, DESDGDT );
     152               1 :     GetMD( 43, DESCLTX );
     153               1 :     GetMD(  1, DESCATP );
     154               1 :     GetMD( 40, DESCAUT );
     155               1 :     GetMD(  1, DESCRSN );
     156               1 :     GetMD(  8, DESSRDT );
     157               1 :     GetMD( 15, DESCTLN );
     158                 : 
     159                 :     /* Load DESID */
     160               1 :     NITFGetField( szDESID, pachHeader, 2, 25);
     161                 : 
     162                 :     /* For NITF < 02.10, we cannot rely on DESID=TRE_OVERFLOW to detect */
     163                 :     /* if DESOFLW and DESITEM are present. So if the next 4 bytes are non */
     164                 :     /* numeric, we'll assume that DESOFLW is there */
     165               1 :     bHasDESOFLW = EQUALN(szDESID, "TRE_OVERFLOW", strlen("TRE_OVERFLOW")) ||
     166                 :        (!((pachHeader[nOffset+0] >= '0' && pachHeader[nOffset+0] <= '9') &&
     167                 :           (pachHeader[nOffset+1] >= '0' && pachHeader[nOffset+1] <= '9') &&
     168                 :           (pachHeader[nOffset+2] >= '0' && pachHeader[nOffset+2] <= '9') &&
     169                 :           (pachHeader[nOffset+3] >= '0' && pachHeader[nOffset+3] <= '9')));
     170                 : 
     171               1 :     if (bHasDESOFLW)
     172                 :     {
     173               1 :         if ((int)psSegInfo->nSegmentHeaderSize < nOffset + 6 + 3 )
     174                 :         {
     175               0 :             CPLError(CE_Failure, CPLE_AppDefined,
     176                 :                         "DES header too small");
     177               0 :             NITFDESDeaccess(psDES);
     178               0 :             return NULL;
     179                 :         }
     180               1 :         GetMD(  6, DESOFLW );
     181               1 :         GetMD(  3, DESITEM );
     182                 :     }
     183                 : 
     184               1 :     if ((int)psSegInfo->nSegmentHeaderSize < nOffset + 4 )
     185                 :     {
     186               0 :         CPLError(CE_Failure, CPLE_AppDefined,
     187                 :                     "DES header too small");
     188               0 :         NITFDESDeaccess(psDES);
     189               0 :         return NULL;
     190                 :     }
     191                 : 
     192               1 :     nDESSHL = atoi(NITFGetField( szTemp, pachHeader, nOffset, 4));
     193               1 :     nOffset += 4;
     194                 : 
     195               1 :     if (nDESSHL < 0)
     196                 :     {
     197               0 :         CPLError(CE_Failure, CPLE_AppDefined,
     198                 :                     "Invalid value for DESSHL");
     199               0 :         NITFDESDeaccess(psDES);
     200               0 :         return NULL;
     201                 :     }
     202               1 :     if ( (int)psSegInfo->nSegmentHeaderSize < nOffset + nDESSHL)
     203                 :     {
     204               0 :         CPLError(CE_Failure, CPLE_AppDefined,
     205                 :                     "DES header too small");
     206               0 :         NITFDESDeaccess(psDES);
     207               0 :         return NULL;
     208                 :     }
     209                 : 
     210               1 :     if (EQUALN(szDESID, "CSSHPA DES", strlen("CSSHPA DES")))
     211                 :     {
     212               0 :         if ( nDESSHL != 62 && nDESSHL != 80)
     213                 :         {
     214               0 :             CPLError(CE_Failure, CPLE_AppDefined,
     215                 :                      "Invalid DESSHL for CSSHPA DES");
     216               0 :             NITFDESDeaccess(psDES);
     217               0 :             return NULL;
     218                 :         }
     219                 : 
     220               0 :         GetMD( 25, SHAPE_USE );
     221               0 :         GetMD( 10, SHAPE_CLASS );
     222               0 :         if (nDESSHL == 80)
     223               0 :             GetMD( 18, CC_SOURCE );
     224               0 :         GetMD(  3, SHAPE1_NAME );
     225               0 :         GetMD(  6, SHAPE1_START );
     226               0 :         GetMD(  3, SHAPE2_NAME );
     227               0 :         GetMD(  6, SHAPE2_START );
     228               0 :         GetMD(  3, SHAPE3_NAME );
     229               0 :         GetMD(  6, SHAPE3_START );
     230                 :     }
     231               1 :     else if (nDESSHL > 0)
     232               0 :         GetMD(  nDESSHL, DESSHF );
     233                 : 
     234               1 :     if ((int)psSegInfo->nSegmentHeaderSize > nOffset)
     235                 :     {
     236                 :         char* pszEscapedDESDATA =
     237                 :                 CPLEscapeString( pachHeader + nOffset, 
     238                 :                                  (int)psSegInfo->nSegmentHeaderSize - nOffset, 
     239               0 :                                  CPLES_BackslashQuotable );
     240               0 :         psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
     241                 :                                                 "NITF_DESDATA",
     242                 :                                                 pszEscapedDESDATA );
     243               0 :         CPLFree(pszEscapedDESDATA);
     244                 :     }
     245                 : 
     246               1 :     return psDES;
     247                 : }
     248                 : 
     249                 : /************************************************************************/
     250                 : /*                           NITFDESDeaccess()                          */
     251                 : /************************************************************************/
     252                 : 
     253                 : void NITFDESDeaccess( NITFDES *psDES )
     254                 : 
     255               1 : {
     256               1 :     CPLAssert( psDES->psFile->pasSegmentInfo[psDES->iSegment].hAccess
     257                 :                == psDES );
     258                 : 
     259               1 :     psDES->psFile->pasSegmentInfo[psDES->iSegment].hAccess = NULL;
     260                 : 
     261               1 :     CPLFree( psDES->pachHeader );
     262               1 :     CSLDestroy( psDES->papszMetadata );
     263                 : 
     264               1 :     CPLFree( psDES );
     265               1 : }
     266                 : 
     267                 : /************************************************************************/
     268                 : /*                              NITFDESGetTRE()                         */
     269                 : /************************************************************************/
     270                 : 
     271                 : /**
     272                 :  * Return the TRE located at nOffset.
     273                 :  *
     274                 :  * @param psDES          descriptor of the DE segment
     275                 :  * @param nOffset        offset of the TRE relative to the beginning of the segment data
     276                 :  * @param szTREName      will be filled with the TRE name
     277                 :  * @param ppabyTREData   will be allocated by the function and filled with the TRE content (in raw form)
     278                 :  * @param pnFoundTRESize will be filled with the TRE size (excluding the first 11 bytes)
     279                 :  * @return TRUE if a TRE was found
     280                 :  */
     281                 : 
     282                 : int   NITFDESGetTRE( NITFDES* psDES,
     283                 :                      int nOffset,
     284                 :                      char szTREName[7],
     285                 :                      char** ppabyTREData,
     286                 :                      int* pnFoundTRESize)
     287               5 : {
     288                 :     char szTREHeader[12];
     289                 :     char szTRETempName[7];
     290                 :     NITFSegmentInfo* psSegInfo;
     291                 :     FILE* fp;
     292                 :     int nTRESize;
     293                 : 
     294               5 :     memset(szTREName, '\0', 7);
     295               5 :     if (ppabyTREData)
     296               5 :         *ppabyTREData = NULL;
     297               5 :     if (pnFoundTRESize)
     298               5 :         *pnFoundTRESize = 0;
     299                 : 
     300               5 :     if (nOffset < 0)
     301               0 :         return FALSE;
     302                 : 
     303               5 :     if (psDES == NULL)
     304               0 :         return FALSE;
     305                 : 
     306               5 :     if (CSLFetchNameValue(psDES->papszMetadata, "NITF_DESOFLW") == NULL)
     307               0 :         return FALSE;
     308                 : 
     309               5 :     psSegInfo = psDES->psFile->pasSegmentInfo + psDES->iSegment;
     310               5 :     fp = psDES->psFile->fp;
     311                 : 
     312               5 :     if (nOffset >= psSegInfo->nSegmentSize)
     313               1 :         return FALSE;
     314                 : 
     315               4 :     VSIFSeekL(fp, psSegInfo->nSegmentStart + nOffset, SEEK_SET);
     316                 : 
     317               4 :     if (VSIFReadL(szTREHeader, 1, 11, fp) != 11)
     318                 :     {
     319                 :         /* Some files have a nSegmentSize larger than what is is in reality */
     320                 :         /* So exit silently if we're at end of file */ 
     321               0 :         VSIFSeekL(fp, 0, SEEK_END);
     322               0 :         if (VSIFTellL(fp) == psSegInfo->nSegmentStart + nOffset)
     323               0 :             return FALSE;
     324                 : 
     325               0 :         CPLError(CE_Failure, CPLE_FileIO,
     326                 :                  "Cannot get 11 bytes at offset " CPL_FRMT_GUIB ".",
     327                 :                  psSegInfo->nSegmentStart + nOffset );
     328               0 :         return FALSE;
     329                 :     }
     330               4 :     szTREHeader[11] = '\0';
     331                 : 
     332               4 :     memcpy(szTRETempName, szTREHeader, 6);
     333               4 :     szTRETempName[6] = '\0';
     334                 : 
     335               4 :     nTRESize = atoi(szTREHeader + 6);
     336               4 :     if (nTRESize < 0)
     337                 :     {
     338               0 :         CPLError(CE_Failure, CPLE_AppDefined,
     339                 :                  "Invalid size (%d) for TRE %s",
     340                 :                  nTRESize, szTRETempName);
     341               0 :         return FALSE;
     342                 :     }
     343               4 :     if (nOffset + 11 + nTRESize > psSegInfo->nSegmentSize)
     344                 :     {
     345               0 :         CPLError(CE_Failure, CPLE_AppDefined,
     346                 :                  "Cannot read %s TRE. Not enough bytes : remaining %d, expected %d",
     347                 :                  szTRETempName,
     348                 :                  (int)(psSegInfo->nSegmentSize - (nOffset + 11)), nTRESize);
     349               0 :         return FALSE;
     350                 :     }
     351                 : 
     352               4 :     if (ppabyTREData)
     353                 :     {
     354                 :         /* Allocate one extra byte for the NULL terminating character */
     355               4 :         *ppabyTREData = (char*) VSIMalloc(nTRESize + 1);
     356               4 :         if (*ppabyTREData  == NULL)
     357                 :         {
     358               0 :             CPLError(CE_Failure, CPLE_OutOfMemory,
     359                 :                     "Cannot allocate %d bytes for TRE %s",
     360                 :                     nTRESize, szTRETempName);
     361               0 :             return FALSE;
     362                 :         }
     363               4 :         (*ppabyTREData)[nTRESize] = '\0';
     364                 : 
     365               4 :         if ((int)VSIFReadL(*ppabyTREData, 1, nTRESize, fp) != nTRESize)
     366                 :         {
     367               0 :             CPLError(CE_Failure, CPLE_FileIO,
     368                 :                      "Cannot get %d bytes at offset " CPL_FRMT_GUIB ".",
     369                 :                      nTRESize, VSIFTellL(fp) );
     370               0 :             VSIFree(*ppabyTREData);
     371               0 :             *ppabyTREData = NULL;
     372               0 :             return FALSE;
     373                 :         }
     374                 :     }
     375                 : 
     376               4 :     strcpy(szTREName, szTRETempName);
     377               4 :     if (pnFoundTRESize)
     378               4 :         *pnFoundTRESize = nTRESize;
     379                 : 
     380               4 :     return TRUE;
     381                 : }
     382                 : 
     383                 : /************************************************************************/
     384                 : /*                           NITFDESFreeTREData()                       */
     385                 : /************************************************************************/
     386                 : 
     387                 : void NITFDESFreeTREData( char* pabyTREData )
     388               4 : {
     389               4 :     VSIFree(pabyTREData);
     390               4 : }
     391                 : 
     392                 : 
     393                 : /************************************************************************/
     394                 : /*                        NITFDESExtractShapefile()                     */
     395                 : /************************************************************************/
     396                 : 
     397                 : int NITFDESExtractShapefile(NITFDES* psDES, const char* pszRadixFileName)
     398               0 : {
     399                 :     NITFSegmentInfo* psSegInfo;
     400                 :     const char* apszExt[3];
     401                 :     int anOffset[4];
     402                 :     int iShpFile;
     403                 :     char* pszFilename;
     404                 : 
     405               0 :     if ( CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE_USE") == NULL )
     406               0 :         return FALSE;
     407                 : 
     408               0 :     psSegInfo = psDES->psFile->pasSegmentInfo + psDES->iSegment;
     409                 : 
     410               0 :     apszExt[0] = CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE1_NAME");
     411               0 :     anOffset[0] = atoi(CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE1_START"));
     412               0 :     apszExt[1] = CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE2_NAME");
     413               0 :     anOffset[1] = atoi(CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE2_START"));
     414               0 :     apszExt[2] = CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE3_NAME");
     415               0 :     anOffset[2] = atoi(CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE3_START"));
     416               0 :     anOffset[3] = (int) psSegInfo->nSegmentSize;
     417                 : 
     418               0 :     for(iShpFile = 0; iShpFile < 3; iShpFile ++)
     419                 :     {
     420               0 :         if (!EQUAL(apszExt[iShpFile], "SHP") &&
     421                 :             !EQUAL(apszExt[iShpFile], "SHX") &&
     422                 :             !EQUAL(apszExt[iShpFile], "DBF"))
     423               0 :             return FALSE;
     424                 : 
     425               0 :         if (anOffset[iShpFile] < 0 ||
     426                 :             anOffset[iShpFile] >= anOffset[iShpFile+1])
     427               0 :             return FALSE;
     428                 :     }
     429                 : 
     430               0 :     pszFilename = (char*) VSIMalloc(strlen(pszRadixFileName) + 4 + 1);
     431               0 :     if (pszFilename == NULL)
     432               0 :         return FALSE;
     433                 : 
     434               0 :     for(iShpFile = 0; iShpFile < 3; iShpFile ++)
     435                 :     {
     436                 :         FILE* fp;
     437                 :         GByte* pabyBuffer;
     438               0 :         int nSize = anOffset[iShpFile+1] - anOffset[iShpFile];
     439                 : 
     440               0 :         pabyBuffer = (GByte*) VSIMalloc(nSize);
     441               0 :         if (pabyBuffer == NULL)
     442                 :         {
     443               0 :             VSIFree(pszFilename);
     444               0 :             return FALSE;
     445                 :         }
     446                 : 
     447               0 :         VSIFSeekL(psDES->psFile->fp, psSegInfo->nSegmentStart + anOffset[iShpFile], SEEK_SET);
     448               0 :         if (VSIFReadL(pabyBuffer, 1, nSize, psDES->psFile->fp) != nSize)
     449                 :         {
     450               0 :             VSIFree(pabyBuffer);
     451               0 :             VSIFree(pszFilename);
     452               0 :             return FALSE;
     453                 :         }
     454                 : 
     455               0 :         sprintf(pszFilename, "%s.%s", pszRadixFileName, apszExt[iShpFile]);
     456               0 :         fp = VSIFOpenL(pszFilename, "wb");
     457               0 :         if (fp == NULL)
     458                 :         {
     459               0 :             VSIFree(pabyBuffer);
     460               0 :             VSIFree(pszFilename);
     461               0 :             return FALSE;
     462                 :         }
     463                 : 
     464               0 :         VSIFWriteL(pabyBuffer, 1, nSize, fp);
     465               0 :         VSIFCloseL(fp);
     466               0 :         VSIFree(pabyBuffer);
     467                 :     }
     468                 : 
     469               0 :     VSIFree(pszFilename);
     470                 : 
     471               0 :     return TRUE;
     472                 : }

Generated by: LTP GCOV extension version 1.5