LCOV - code coverage report
Current view: directory - frmts/nitf - nitfdes.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 241 124 51.5 %
Date: 2012-04-28 Functions: 5 4 80.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: nitfdes.c 23033 2011-09-03 18:46:11Z 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 23033 2011-09-03 18:46:11Z rouault $");
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                          NITFDESAccess()                             */
      40                 : /************************************************************************/
      41                 : 
      42               4 : NITFDES *NITFDESAccess( NITFFile *psFile, int iSegment )
      43                 : 
      44                 : {
      45                 :     NITFDES   *psDES;
      46                 :     char      *pachHeader;
      47                 :     NITFSegmentInfo *psSegInfo;
      48                 :     char       szDESID[26];
      49                 :     int        nOffset;
      50                 :     int        bHasDESOFLW;
      51                 :     int        nDESSHL;
      52                 :     
      53                 : /* -------------------------------------------------------------------- */
      54                 : /*      Verify segment, and return existing DES accessor if there       */
      55                 : /*      is one.                                                         */
      56                 : /* -------------------------------------------------------------------- */
      57               4 :     if( iSegment < 0 || iSegment >= psFile->nSegmentCount )
      58               0 :         return NULL;
      59                 : 
      60               4 :     psSegInfo = psFile->pasSegmentInfo + iSegment;
      61                 : 
      62               4 :     if( !EQUAL(psSegInfo->szSegmentType,"DE") )
      63               0 :         return NULL;
      64                 : 
      65               4 :     if( psSegInfo->hAccess != NULL )
      66               0 :         return (NITFDES *) psSegInfo->hAccess;
      67                 : 
      68                 : /* -------------------------------------------------------------------- */
      69                 : /*      Read the DES subheader.                                         */
      70                 : /* -------------------------------------------------------------------- */
      71               4 :     if (psSegInfo->nSegmentHeaderSize < 200)
      72                 :     {
      73               0 :         CPLError(CE_Failure, CPLE_AppDefined,
      74                 :                     "DES header too small");
      75               0 :         return NULL;
      76                 :     }
      77                 : 
      78               4 :     pachHeader = (char*) VSIMalloc(psSegInfo->nSegmentHeaderSize);
      79               4 :     if (pachHeader == NULL)
      80                 :     {
      81               0 :         CPLError(CE_Failure, CPLE_OutOfMemory,
      82                 :                  "Cannot allocate memory for segment header");
      83               0 :         return NULL;
      84                 :     }
      85                 : 
      86                 : retry:
      87               8 :     if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart, 
      88                 :                   SEEK_SET ) != 0 
      89               8 :         || VSIFReadL( pachHeader, 1, psSegInfo->nSegmentHeaderSize, 
      90               8 :                      psFile->fp ) != psSegInfo->nSegmentHeaderSize )
      91                 :     {
      92               0 :         CPLError( CE_Failure, CPLE_FileIO, 
      93                 :                   "Failed to read %u byte DES subheader from " CPL_FRMT_GUIB ".",
      94                 :                   psSegInfo->nSegmentHeaderSize,
      95                 :                   psSegInfo->nSegmentHeaderStart );
      96               0 :         CPLFree(pachHeader);
      97               0 :         return NULL;
      98                 :     }
      99                 : 
     100               4 :     if (!EQUALN(pachHeader, "DE", 2))
     101                 :     {
     102               0 :         if (EQUALN(pachHeader + 4, "DERegistered", 12))
     103                 :         {
     104                 :             /* BAO_46_Ed1/rpf/conc/concz10/000fz010.ona and cie are buggy */
     105               0 :             CPLDebug("NITF", "Patching nSegmentHeaderStart and nSegmentStart for DE segment %d", iSegment);
     106               0 :             psSegInfo->nSegmentHeaderStart += 4;
     107               0 :             psSegInfo->nSegmentStart += 4;
     108               0 :             goto retry;
     109                 :         }
     110                 : 
     111               0 :         CPLError(CE_Failure, CPLE_AppDefined,
     112                 :                  "Invalid segment prefix for DE segment %d", iSegment);
     113                 : 
     114               0 :         CPLFree(pachHeader);
     115               0 :         return NULL;
     116                 :     }
     117                 : 
     118                 : /* -------------------------------------------------------------------- */
     119                 : /*      Initialize DES object.                                          */
     120                 : /* -------------------------------------------------------------------- */
     121               4 :     psDES = (NITFDES *) CPLCalloc(sizeof(NITFDES),1);
     122                 : 
     123               4 :     psDES->psFile = psFile;
     124               4 :     psDES->iSegment = iSegment;
     125               4 :     psDES->pachHeader = pachHeader;
     126                 : 
     127               4 :     psSegInfo->hAccess = psDES;
     128                 : 
     129                 : /* -------------------------------------------------------------------- */
     130                 : /*      Collect a variety of information as metadata.                   */
     131                 : /* -------------------------------------------------------------------- */
     132                 : #define GetMD( length, name )              \
     133                 :     do { NITFExtractMetadata( &(psDES->papszMetadata), pachHeader,    \
     134                 :                          nOffset, length,                        \
     135                 :                          "NITF_" #name ); \
     136                 :     nOffset += length; } while(0)
     137                 : 
     138               4 :     nOffset = 2;
     139               4 :     GetMD( 25, DESID  );
     140               4 :     GetMD(  2, DESVER );
     141               4 :     GetMD(  1, DECLAS );
     142               4 :     GetMD(  2, DESCLSY );
     143               4 :     GetMD( 11, DESCODE );
     144               4 :     GetMD(  2, DESCTLH );
     145               4 :     GetMD( 20, DESREL  );
     146               4 :     GetMD(  2, DESDCTP );
     147               4 :     GetMD(  8, DESDCDT );
     148               4 :     GetMD(  4, DESDCXM );
     149               4 :     GetMD(  1, DESDG   );
     150               4 :     GetMD(  8, DESDGDT );
     151               4 :     GetMD( 43, DESCLTX );
     152               4 :     GetMD(  1, DESCATP );
     153               4 :     GetMD( 40, DESCAUT );
     154               4 :     GetMD(  1, DESCRSN );
     155               4 :     GetMD(  8, DESSRDT );
     156               4 :     GetMD( 15, DESCTLN );
     157                 : 
     158                 :     /* Load DESID */
     159               4 :     NITFGetField( szDESID, pachHeader, 2, 25);
     160                 : 
     161                 :     /* For NITF < 02.10, we cannot rely on DESID=TRE_OVERFLOW to detect */
     162                 :     /* if DESOFLW and DESITEM are present. So if the next 4 bytes are non */
     163                 :     /* numeric, we'll assume that DESOFLW is there */
     164              20 :     bHasDESOFLW = EQUALN(szDESID, "TRE_OVERFLOW", strlen("TRE_OVERFLOW")) ||
     165               4 :        (!((pachHeader[nOffset+0] >= '0' && pachHeader[nOffset+0] <= '9') &&
     166               4 :           (pachHeader[nOffset+1] >= '0' && pachHeader[nOffset+1] <= '9') &&
     167               4 :           (pachHeader[nOffset+2] >= '0' && pachHeader[nOffset+2] <= '9') &&
     168               4 :           (pachHeader[nOffset+3] >= '0' && pachHeader[nOffset+3] <= '9')));
     169                 : 
     170               4 :     if (bHasDESOFLW)
     171                 :     {
     172               2 :         if ((int)psSegInfo->nSegmentHeaderSize < nOffset + 6 + 3 )
     173                 :         {
     174               0 :             CPLError(CE_Failure, CPLE_AppDefined,
     175                 :                         "DES header too small");
     176               0 :             NITFDESDeaccess(psDES);
     177               0 :             return NULL;
     178                 :         }
     179               2 :         GetMD(  6, DESOFLW );
     180               2 :         GetMD(  3, DESITEM );
     181                 :     }
     182                 : 
     183               4 :     if ((int)psSegInfo->nSegmentHeaderSize < nOffset + 4 )
     184                 :     {
     185               0 :         CPLError(CE_Failure, CPLE_AppDefined,
     186                 :                     "DES header too small");
     187               0 :         NITFDESDeaccess(psDES);
     188               0 :         return NULL;
     189                 :     }
     190                 : 
     191               4 :     GetMD( 4, DESSHL );
     192               4 :     nDESSHL = atoi(CSLFetchNameValue( psDES->papszMetadata, "NITF_DESSHL" ) );
     193                 : 
     194               4 :     if (nDESSHL < 0)
     195                 :     {
     196               0 :         CPLError(CE_Failure, CPLE_AppDefined,
     197                 :                     "Invalid value for DESSHL");
     198               0 :         NITFDESDeaccess(psDES);
     199               0 :         return NULL;
     200                 :     }
     201               4 :     if ( (int)psSegInfo->nSegmentHeaderSize < nOffset + nDESSHL)
     202                 :     {
     203               0 :         CPLError(CE_Failure, CPLE_AppDefined,
     204                 :                     "DES header too small");
     205               0 :         NITFDESDeaccess(psDES);
     206               0 :         return NULL;
     207                 :     }
     208                 : 
     209               4 :     if (EQUALN(szDESID, "CSSHPA DES", strlen("CSSHPA DES")))
     210                 :     {
     211               0 :         if ( nDESSHL != 62 && nDESSHL != 80)
     212                 :         {
     213               0 :             CPLError(CE_Failure, CPLE_AppDefined,
     214                 :                      "Invalid DESSHL for CSSHPA DES");
     215               0 :             NITFDESDeaccess(psDES);
     216               0 :             return NULL;
     217                 :         }
     218                 : 
     219               0 :         GetMD( 25, SHAPE_USE );
     220               0 :         GetMD( 10, SHAPE_CLASS );
     221               0 :         if (nDESSHL == 80)
     222               0 :             GetMD( 18, CC_SOURCE );
     223               0 :         GetMD(  3, SHAPE1_NAME );
     224               0 :         GetMD(  6, SHAPE1_START );
     225               0 :         GetMD(  3, SHAPE2_NAME );
     226               0 :         GetMD(  6, SHAPE2_START );
     227               0 :         GetMD(  3, SHAPE3_NAME );
     228               0 :         GetMD(  6, SHAPE3_START );
     229                 :     }
     230               4 :     else if (EQUALN(szDESID, "XML_DATA_CONTENT", strlen("XML_DATA_CONTENT")))
     231                 :     {
     232                 :         /* TODO : handle nDESSHL = 0005 and 0283 */
     233               2 :         if (nDESSHL >= 5)
     234                 :         {
     235               2 :             GetMD( 5, DESCRC );
     236               2 :             if (nDESSHL >= 283)
     237                 :             {
     238               2 :                 GetMD( 8, DESSHFT );
     239               2 :                 GetMD( 20, DESSHDT );
     240               2 :                 GetMD( 40, DESSHRP );
     241               2 :                 GetMD( 60, DESSHSI );
     242               2 :                 GetMD( 10, DESSHSV );
     243               2 :                 GetMD( 20, DESSHSD );
     244               2 :                 GetMD( 120, DESSHTN );
     245               2 :                 if (nDESSHL >= 773)
     246                 :                 {
     247               2 :                     GetMD( 125, DESSHLPG );
     248               2 :                     GetMD( 25, DESSHLPT );
     249               2 :                     GetMD( 20, DESSHLI );
     250               2 :                     GetMD( 120, DESSHLIN );
     251               2 :                     GetMD( 200, DESSHABS );
     252                 :                 }
     253                 :             }
     254                 :         }
     255                 :     }
     256               2 :     else if (EQUALN(szDESID, "CSATTA DES", strlen("CSATTA DES")) && nDESSHL == 52)
     257                 :     {
     258               0 :         GetMD( 12, ATT_TYPE );
     259               0 :         GetMD( 14, DT_ATT );
     260               0 :         GetMD( 8, DATE_ATT );
     261               0 :         GetMD( 13, T0_ATT );
     262               0 :         GetMD( 5, NUM_ATT );
     263                 :     }
     264               2 :     else if (nDESSHL > 0)
     265               0 :         GetMD(  nDESSHL, DESSHF );
     266                 : 
     267               4 :     if ((int)psSegInfo->nSegmentHeaderSize > nOffset)
     268                 :     {
     269                 :         char* pszEscapedDESDATA =
     270               0 :                 CPLEscapeString( pachHeader + nOffset, 
     271                 :                                  (int)psSegInfo->nSegmentHeaderSize - nOffset, 
     272               0 :                                  CPLES_BackslashQuotable );
     273               0 :         psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
     274                 :                                                 "NITF_DESDATA",
     275                 :                                                 pszEscapedDESDATA );
     276               0 :         CPLFree(pszEscapedDESDATA);
     277                 :     }
     278                 :     else
     279                 :     {
     280               4 :         char* pachData = (char*)VSIMalloc((size_t)psSegInfo->nSegmentSize);
     281               4 :         if (pachData == NULL )
     282                 :         {
     283               0 :             CPLDebug("NITF", "Cannot allocate " CPL_FRMT_GUIB " bytes DES data",
     284                 :                      psSegInfo->nSegmentSize);
     285                 :         }
     286               8 :         else if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentStart,
     287                 :                     SEEK_SET ) != 0
     288               4 :             || VSIFReadL( pachData, 1, (size_t)psSegInfo->nSegmentSize,
     289               4 :                         psFile->fp ) != psSegInfo->nSegmentSize )
     290                 :         {
     291               0 :             CPLDebug("NITF",
     292                 :                     "Failed to read " CPL_FRMT_GUIB" bytes DES data from " CPL_FRMT_GUIB ".",
     293                 :                     psSegInfo->nSegmentSize,
     294                 :                     psSegInfo->nSegmentStart );
     295                 :         }
     296                 :         else
     297                 :         {
     298                 :             char* pszEscapedDESDATA =
     299               4 :                     CPLEscapeString( pachData,
     300                 :                                     (int)psSegInfo->nSegmentSize,
     301               4 :                                     CPLES_BackslashQuotable );
     302               4 :             psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
     303                 :                                                     "NITF_DESDATA",
     304                 :                                                     pszEscapedDESDATA );
     305               4 :             CPLFree(pszEscapedDESDATA);
     306                 :         }
     307                 : 
     308                 : #ifdef notdef
     309                 :         /* Disabled because might generate a huge amount of elements */
     310                 :         if (EQUALN(szDESID, "CSATTA DES", strlen("CSATTA DES")))
     311                 :         {
     312                 :             int nNumAtt = atoi(CSLFetchNameValueDef(psDES->papszMetadata, "NITF_NUM_ATT", "0"));
     313                 :             if (nNumAtt * 8 * 4 == psSegInfo->nSegmentSize)
     314                 :             {
     315                 :                 int nMDSize = CSLCount(psDES->papszMetadata);
     316                 :                 char** papszMD = (char**)VSIRealloc(psDES->papszMetadata, (nMDSize + nNumAtt * 4 + 1) * sizeof(char*));
     317                 :                 if (papszMD)
     318                 :                 {
     319                 :                     int i, j;
     320                 :                     const GByte* pachDataIter = pachData;
     321                 : 
     322                 :                     psDES->papszMetadata = papszMD;
     323                 :                     for(i=0;i<nNumAtt;i++)
     324                 :                     {
     325                 :                         char szAttrNameValue[64+1+256+1];
     326                 :                         double dfVal;
     327                 :                         for(j=0;j<4;j++)
     328                 :                         {
     329                 :                             memcpy(&dfVal, pachDataIter, 8);
     330                 :                             CPL_MSBPTR64(&dfVal);
     331                 :                             pachDataIter += 8;
     332                 :                             sprintf(szAttrNameValue, "NITF_ATT_Q%d_%d=%.16g", j+1, i, dfVal);
     333                 :                             papszMD[nMDSize + i * 4 + j] = CPLStrdup(szAttrNameValue);
     334                 :                         }
     335                 :                     }
     336                 :                     papszMD[nMDSize + nNumAtt * 4] = NULL;
     337                 :                 }
     338                 :             }
     339                 :         }
     340                 : #endif
     341                 : 
     342               4 :         CPLFree(pachData);
     343                 :     }
     344                 : 
     345               4 :     return psDES;
     346                 : }
     347                 : 
     348                 : /************************************************************************/
     349                 : /*                           NITFDESDeaccess()                          */
     350                 : /************************************************************************/
     351                 : 
     352               4 : void NITFDESDeaccess( NITFDES *psDES )
     353                 : 
     354                 : {
     355               4 :     CPLAssert( psDES->psFile->pasSegmentInfo[psDES->iSegment].hAccess
     356                 :                == psDES );
     357                 : 
     358               4 :     psDES->psFile->pasSegmentInfo[psDES->iSegment].hAccess = NULL;
     359                 : 
     360               4 :     CPLFree( psDES->pachHeader );
     361               4 :     CSLDestroy( psDES->papszMetadata );
     362                 : 
     363               4 :     CPLFree( psDES );
     364               4 : }
     365                 : 
     366                 : /************************************************************************/
     367                 : /*                              NITFDESGetTRE()                         */
     368                 : /************************************************************************/
     369                 : 
     370                 : /**
     371                 :  * Return the TRE located at nOffset.
     372                 :  *
     373                 :  * @param psDES          descriptor of the DE segment
     374                 :  * @param nOffset        offset of the TRE relative to the beginning of the segment data
     375                 :  * @param szTREName      will be filled with the TRE name
     376                 :  * @param ppabyTREData   will be allocated by the function and filled with the TRE content (in raw form)
     377                 :  * @param pnFoundTRESize will be filled with the TRE size (excluding the first 11 bytes)
     378                 :  * @return TRUE if a TRE was found
     379                 :  */
     380                 : 
     381              12 : int   NITFDESGetTRE( NITFDES* psDES,
     382                 :                      int nOffset,
     383                 :                      char szTREName[7],
     384                 :                      char** ppabyTREData,
     385                 :                      int* pnFoundTRESize)
     386                 : {
     387                 :     char szTREHeader[12];
     388                 :     char szTRETempName[7];
     389                 :     NITFSegmentInfo* psSegInfo;
     390                 :     VSILFILE* fp;
     391                 :     int nTRESize;
     392                 : 
     393              12 :     memset(szTREName, '\0', 7);
     394              12 :     if (ppabyTREData)
     395              12 :         *ppabyTREData = NULL;
     396              12 :     if (pnFoundTRESize)
     397              12 :         *pnFoundTRESize = 0;
     398                 : 
     399              12 :     if (nOffset < 0)
     400               0 :         return FALSE;
     401                 : 
     402              12 :     if (psDES == NULL)
     403               0 :         return FALSE;
     404                 : 
     405              12 :     if (CSLFetchNameValue(psDES->papszMetadata, "NITF_DESOFLW") == NULL)
     406               2 :         return FALSE;
     407                 : 
     408              10 :     psSegInfo = psDES->psFile->pasSegmentInfo + psDES->iSegment;
     409              10 :     fp = psDES->psFile->fp;
     410                 : 
     411              10 :     if (nOffset >= psSegInfo->nSegmentSize)
     412               2 :         return FALSE;
     413                 : 
     414               8 :     VSIFSeekL(fp, psSegInfo->nSegmentStart + nOffset, SEEK_SET);
     415                 : 
     416               8 :     if (VSIFReadL(szTREHeader, 1, 11, fp) != 11)
     417                 :     {
     418                 :         /* Some files have a nSegmentSize larger than what is is in reality */
     419                 :         /* So exit silently if we're at end of file */ 
     420               0 :         VSIFSeekL(fp, 0, SEEK_END);
     421               0 :         if (VSIFTellL(fp) == psSegInfo->nSegmentStart + nOffset)
     422               0 :             return FALSE;
     423                 : 
     424               0 :         CPLError(CE_Failure, CPLE_FileIO,
     425                 :                  "Cannot get 11 bytes at offset " CPL_FRMT_GUIB ".",
     426                 :                  psSegInfo->nSegmentStart + nOffset );
     427               0 :         return FALSE;
     428                 :     }
     429               8 :     szTREHeader[11] = '\0';
     430                 : 
     431               8 :     memcpy(szTRETempName, szTREHeader, 6);
     432               8 :     szTRETempName[6] = '\0';
     433                 : 
     434               8 :     nTRESize = atoi(szTREHeader + 6);
     435               8 :     if (nTRESize < 0)
     436                 :     {
     437               0 :         CPLError(CE_Failure, CPLE_AppDefined,
     438                 :                  "Invalid size (%d) for TRE %s",
     439                 :                  nTRESize, szTRETempName);
     440               0 :         return FALSE;
     441                 :     }
     442               8 :     if (nOffset + 11 + nTRESize > psSegInfo->nSegmentSize)
     443                 :     {
     444               0 :         CPLError(CE_Failure, CPLE_AppDefined,
     445                 :                  "Cannot read %s TRE. Not enough bytes : remaining %d, expected %d",
     446                 :                  szTRETempName,
     447                 :                  (int)(psSegInfo->nSegmentSize - (nOffset + 11)), nTRESize);
     448               0 :         return FALSE;
     449                 :     }
     450                 : 
     451               8 :     if (ppabyTREData)
     452                 :     {
     453                 :         /* Allocate one extra byte for the NULL terminating character */
     454               8 :         *ppabyTREData = (char*) VSIMalloc(nTRESize + 1);
     455               8 :         if (*ppabyTREData  == NULL)
     456                 :         {
     457               0 :             CPLError(CE_Failure, CPLE_OutOfMemory,
     458                 :                     "Cannot allocate %d bytes for TRE %s",
     459                 :                     nTRESize, szTRETempName);
     460               0 :             return FALSE;
     461                 :         }
     462               8 :         (*ppabyTREData)[nTRESize] = '\0';
     463                 : 
     464               8 :         if ((int)VSIFReadL(*ppabyTREData, 1, nTRESize, fp) != nTRESize)
     465                 :         {
     466               0 :             CPLError(CE_Failure, CPLE_FileIO,
     467                 :                      "Cannot get %d bytes at offset " CPL_FRMT_GUIB ".",
     468                 :                      nTRESize, VSIFTellL(fp) );
     469               0 :             VSIFree(*ppabyTREData);
     470               0 :             *ppabyTREData = NULL;
     471               0 :             return FALSE;
     472                 :         }
     473                 :     }
     474                 : 
     475               8 :     strcpy(szTREName, szTRETempName);
     476               8 :     if (pnFoundTRESize)
     477               8 :         *pnFoundTRESize = nTRESize;
     478                 : 
     479               8 :     return TRUE;
     480                 : }
     481                 : 
     482                 : /************************************************************************/
     483                 : /*                           NITFDESFreeTREData()                       */
     484                 : /************************************************************************/
     485                 : 
     486               8 : void NITFDESFreeTREData( char* pabyTREData )
     487                 : {
     488               8 :     VSIFree(pabyTREData);
     489               8 : }
     490                 : 
     491                 : 
     492                 : /************************************************************************/
     493                 : /*                        NITFDESExtractShapefile()                     */
     494                 : /************************************************************************/
     495                 : 
     496               0 : int NITFDESExtractShapefile(NITFDES* psDES, const char* pszRadixFileName)
     497                 : {
     498                 :     NITFSegmentInfo* psSegInfo;
     499                 :     const char* apszExt[3];
     500                 :     int anOffset[4];
     501                 :     int iShpFile;
     502                 :     char* pszFilename;
     503                 : 
     504               0 :     if ( CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE_USE") == NULL )
     505               0 :         return FALSE;
     506                 : 
     507               0 :     psSegInfo = psDES->psFile->pasSegmentInfo + psDES->iSegment;
     508                 : 
     509               0 :     apszExt[0] = CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE1_NAME");
     510               0 :     anOffset[0] = atoi(CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE1_START"));
     511               0 :     apszExt[1] = CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE2_NAME");
     512               0 :     anOffset[1] = atoi(CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE2_START"));
     513               0 :     apszExt[2] = CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE3_NAME");
     514               0 :     anOffset[2] = atoi(CSLFetchNameValue(psDES->papszMetadata, "NITF_SHAPE3_START"));
     515               0 :     anOffset[3] = (int) psSegInfo->nSegmentSize;
     516                 : 
     517               0 :     for(iShpFile = 0; iShpFile < 3; iShpFile ++)
     518                 :     {
     519               0 :         if (!EQUAL(apszExt[iShpFile], "SHP") &&
     520               0 :             !EQUAL(apszExt[iShpFile], "SHX") &&
     521               0 :             !EQUAL(apszExt[iShpFile], "DBF"))
     522               0 :             return FALSE;
     523                 : 
     524               0 :         if (anOffset[iShpFile] < 0 ||
     525               0 :             anOffset[iShpFile] >= anOffset[iShpFile+1])
     526               0 :             return FALSE;
     527                 :     }
     528                 : 
     529               0 :     pszFilename = (char*) VSIMalloc(strlen(pszRadixFileName) + 4 + 1);
     530               0 :     if (pszFilename == NULL)
     531               0 :         return FALSE;
     532                 : 
     533               0 :     for(iShpFile = 0; iShpFile < 3; iShpFile ++)
     534                 :     {
     535                 :         VSILFILE* fp;
     536                 :         GByte* pabyBuffer;
     537               0 :         int nSize = anOffset[iShpFile+1] - anOffset[iShpFile];
     538                 : 
     539               0 :         pabyBuffer = (GByte*) VSIMalloc(nSize);
     540               0 :         if (pabyBuffer == NULL)
     541                 :         {
     542               0 :             VSIFree(pszFilename);
     543               0 :             return FALSE;
     544                 :         }
     545                 : 
     546               0 :         VSIFSeekL(psDES->psFile->fp, psSegInfo->nSegmentStart + anOffset[iShpFile], SEEK_SET);
     547               0 :         if (VSIFReadL(pabyBuffer, 1, nSize, psDES->psFile->fp) != nSize)
     548                 :         {
     549               0 :             VSIFree(pabyBuffer);
     550               0 :             VSIFree(pszFilename);
     551               0 :             return FALSE;
     552                 :         }
     553                 : 
     554               0 :         sprintf(pszFilename, "%s.%s", pszRadixFileName, apszExt[iShpFile]);
     555               0 :         fp = VSIFOpenL(pszFilename, "wb");
     556               0 :         if (fp == NULL)
     557                 :         {
     558               0 :             VSIFree(pabyBuffer);
     559               0 :             VSIFree(pszFilename);
     560               0 :             return FALSE;
     561                 :         }
     562                 : 
     563               0 :         VSIFWriteL(pabyBuffer, 1, nSize, fp);
     564               0 :         VSIFCloseL(fp);
     565               0 :         VSIFree(pabyBuffer);
     566                 :     }
     567                 : 
     568               0 :     VSIFree(pszFilename);
     569                 : 
     570               0 :     return TRUE;
     571                 : }

Generated by: LCOV version 1.7