LCOV - code coverage report
Current view: top level - frmts/miramon_common - mm_gdal_functions.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 838 1387 60.4 %
Date: 2026-02-12 23:49:34 Functions: 45 47 95.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  C MiraMon code adapted to be used in GDAL
       5             :  * Author:   Abel Pau, a.pau@creaf.uab.cat, based on the MiraMon codes,
       6             :  *           mainly written by Xavier Pons, Joan Maso (correctly written
       7             :  *           "Mas0xF3"), Abel Pau, Nuria Julia (N0xFAria Juli0xE0),
       8             :  *           Xavier Calaf, Lluis (Llu0xEDs) Pesquer and Alaitz Zabala, from
       9             :  *           CREAF and Universitat Autonoma (Aut0xF2noma) de Barcelona.
      10             :  *           For a complete list of contributors:
      11             :  *           https://www.miramon.cat/eng/QuiSom.htm
      12             :  ******************************************************************************
      13             :  * Copyright (c) 2024, Xavier Pons
      14             :  *
      15             :  * SPDX-License-Identifier: MIT
      16             :  ****************************************************************************/
      17             : 
      18             : #include "ogr_api.h"            // For CPL_C_START
      19             : #include "mm_gdal_functions.h"  // For CPLStrlcpy()
      20             : #ifdef EMBED_RESOURCE_FILES
      21             : #include "embedded_resources.h"
      22             : #endif
      23             : 
      24             : CPL_C_START              // Necessary for compiling in GDAL project
      25             : #include "cpl_string.h"  // For CPL_ENC_UTF8
      26             : 
      27             :     const char *MM_pszLogFilename = nullptr;
      28             : 
      29             : static const char MM_EmptyString[] = {""};
      30             : #define MM_SetEndOfString (*MM_EmptyString)
      31             : 
      32        1538 : CPL_DLL void fclose_and_nullify(VSILFILE **pFunc)
      33             : {
      34        1538 :     if (!pFunc || !(*pFunc))
      35         359 :         return;
      36        1179 :     VSIFCloseL(*pFunc);
      37        1179 :     *pFunc = nullptr;
      38             : }
      39             : 
      40             : // CREATING AN EXTENDED MIRAMON DBF
      41        4256 : CPL_DLL void MM_InitializeField(struct MM_FIELD *pField)
      42             : {
      43        4256 :     memset(pField, '\0', sizeof(*pField));
      44        4256 :     pField->FieldType = 'C';
      45        4256 :     pField->GeoTopoTypeField = MM_NO_ES_CAMP_GEOTOPO;
      46        4256 : }
      47             : 
      48             : #define MM_ACCEPTABLE_NUMBER_OF_FIELDS 20000
      49             : 
      50         337 : CPL_DLL struct MM_FIELD *MM_CreateAllFields(MM_EXT_DBF_N_FIELDS nFields)
      51             : {
      52             :     struct MM_FIELD *camp;
      53             :     MM_EXT_DBF_N_FIELDS i;
      54             : 
      55             :     // MiraMon could accept a number of fields 13.4 million
      56             :     // but GDAL prefers to limit that to 20.000 to avoid
      57             :     // too large memory allocation attempts with corrupted datasets
      58         337 :     if (nFields > MM_ACCEPTABLE_NUMBER_OF_FIELDS)
      59             :     {
      60           0 :         CPLError(CE_Failure, CPLE_OutOfMemory,
      61             :                  "More than 20000 fields not accepted");
      62           0 :         return nullptr;
      63             :     }
      64             : 
      65             : #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
      66         337 :     if (nFields >= UINT32_MAX / sizeof(*camp))
      67           0 :         return nullptr;
      68             : #else
      69             :     if (nFields >= (1000U * 1000 * 1000) / sizeof(*camp))
      70             :         return nullptr;
      71             : #endif
      72             : 
      73         337 :     if ((camp = VSICalloc(nFields, sizeof(*camp))) == nullptr)
      74           0 :         return nullptr;
      75             : 
      76        2781 :     for (i = 0; i < nFields; i++)
      77        2444 :         MM_InitializeField(camp + i);
      78         337 :     return camp;
      79             : }
      80             : 
      81         194 : static struct MM_DATA_BASE_XP *MM_CreateEmptyHeader(MM_EXT_DBF_N_FIELDS nFields)
      82             : {
      83             :     struct MM_DATA_BASE_XP *data_base_XP;
      84             : 
      85         194 :     if ((data_base_XP = (struct MM_DATA_BASE_XP *)VSICalloc(
      86             :              1, sizeof(struct MM_DATA_BASE_XP))) == nullptr)
      87           0 :         return nullptr;
      88             : 
      89         194 :     if (nFields == 0)
      90             :     {
      91             :         ;
      92             :     }
      93             :     else
      94             :     {
      95         194 :         data_base_XP->pField = (struct MM_FIELD *)MM_CreateAllFields(nFields);
      96         194 :         if (!data_base_XP->pField)
      97             :         {
      98           0 :             VSIFree(data_base_XP);
      99           0 :             return nullptr;
     100             :         }
     101             :     }
     102         194 :     data_base_XP->nFields = nFields;
     103         194 :     return data_base_XP;
     104             : }
     105             : 
     106         194 : CPL_DLL struct MM_DATA_BASE_XP *MM_CreateDBFHeader(MM_EXT_DBF_N_FIELDS n_camps,
     107             :                                                    MM_BYTE charset)
     108             : {
     109             :     struct MM_DATA_BASE_XP *bd_xp;
     110             :     struct MM_FIELD *camp;
     111             :     MM_EXT_DBF_N_FIELDS i;
     112             : 
     113         194 :     if (nullptr == (bd_xp = MM_CreateEmptyHeader(n_camps)))
     114           0 :         return nullptr;
     115             : 
     116         194 :     bd_xp->CharSet = charset;
     117             : 
     118         194 :     strcpy(bd_xp->ReadingMode, "a+b");
     119             : 
     120         194 :     bd_xp->IdGraficField = n_camps;
     121         194 :     bd_xp->IdEntityField = MM_MAX_EXT_DBF_N_FIELDS_TYPE;
     122         194 :     bd_xp->dbf_version = (MM_BYTE)((n_camps > MM_MAX_N_CAMPS_DBF_CLASSICA)
     123             :                                        ? MM_MARCA_VERSIO_1_DBF_ESTESA
     124             :                                        : MM_MARCA_DBASE4);
     125             : 
     126        1430 :     for (i = 0, camp = bd_xp->pField; i < n_camps; i++, camp++)
     127             :     {
     128        1236 :         MM_InitializeField(camp);
     129        1236 :         if (i < 99999)
     130        1236 :             snprintf(camp->FieldName, sizeof(camp->FieldName), "CAMP%05u",
     131        1236 :                      (unsigned)(i + 1));
     132             :         else
     133           0 :             snprintf(camp->FieldName, sizeof(camp->FieldName), "CM%u",
     134           0 :                      (unsigned)(i + 1));
     135        1236 :         camp->FieldType = 'C';
     136        1236 :         camp->DecimalsIfFloat = 0;
     137        1236 :         camp->BytesPerField = 50;
     138             :     }
     139         194 :     return bd_xp;
     140             : }
     141             : 
     142        1236 : static MM_BYTE MM_GetDefaultDesiredDBFFieldWidth(const struct MM_FIELD *camp)
     143             : {
     144             :     size_t a, b, c, d, e;
     145             : 
     146        1236 :     b = strlen(camp->FieldName);
     147        1236 :     c = strlen(camp->FieldDescription[0]);
     148             : 
     149        1236 :     if (camp->FieldType == 'D')
     150             :     {
     151          68 :         d = (b > c ? b : c);
     152          68 :         a = (size_t)camp->BytesPerField + 2;
     153          68 :         return (MM_BYTE)(a > d ? a : d);
     154             :     }
     155        1168 :     a = camp->BytesPerField;
     156        1168 :     d = (unsigned int)(b > c ? b : c);
     157        1168 :     e = (a > d ? a : d);
     158        1168 :     return (MM_BYTE)(e < 80 ? e : 80);
     159             : }
     160             : 
     161        9122 : static MM_BOOLEAN MM_is_field_name_lowercase(const char *szChain)
     162             : {
     163             :     const char *p;
     164             : 
     165       56634 :     for (p = szChain; *p; p++)
     166             :     {
     167       50839 :         if ((*p >= 'a' && *p <= 'z'))
     168        3327 :             return TRUE;
     169             :     }
     170        5795 :     return FALSE;
     171             : }
     172             : 
     173             : static MM_BOOLEAN
     174        9154 : MM_Is_classical_DBF_field_name_or_lowercase(const char *szChain)
     175             : {
     176             :     const char *p;
     177             : 
     178       77114 :     for (p = szChain; *p; p++)
     179             :     {
     180       67992 :         if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
     181        6335 :             (*p >= '0' && *p <= '9') || *p == '_')
     182             :             ;
     183             :         else
     184          32 :             return FALSE;
     185             :     }
     186        9122 :     if (szChain[0] == '_')
     187           0 :         return FALSE;
     188        9122 :     return TRUE;
     189             : }
     190             : 
     191             : static MM_BOOLEAN
     192       81935 : MM_Is_character_valid_for_extended_DBF_field_name(int valor,
     193             :                                                   int *valor_substitut)
     194             : {
     195       81935 :     if (valor_substitut)
     196             :     {
     197           0 :         switch (valor)
     198             :         {
     199           0 :             case 32:
     200           0 :                 *valor_substitut = '_';
     201           0 :                 return FALSE;
     202           0 :             case 91:
     203           0 :                 *valor_substitut = '(';
     204           0 :                 return FALSE;
     205           0 :             case 93:
     206           0 :                 *valor_substitut = ')';
     207           0 :                 return FALSE;
     208           0 :             case 96:
     209           0 :                 *valor_substitut = '\'';
     210           0 :                 return FALSE;
     211           0 :             case 127:
     212           0 :                 *valor_substitut = '_';
     213           0 :                 return FALSE;
     214           0 :             case 168:
     215           0 :                 *valor_substitut = '-';
     216           0 :                 return FALSE;
     217             :         }
     218             :     }
     219             :     else
     220             :     {
     221       81935 :         if (valor < 32 || valor == 91 || valor == 93 || valor == 96 ||
     222       81935 :             valor == 127 || valor == 168)
     223           0 :             return FALSE;
     224             :     }
     225       81935 :     return TRUE;
     226             : }
     227             : 
     228       10272 : CPL_DLL int MM_ISExtendedNameBD_XP(const char *nom_camp)
     229             : {
     230             :     size_t mida, j;
     231             : 
     232       10272 :     mida = strlen(nom_camp);
     233       10272 :     if (mida >= MM_MAX_LON_FIELD_NAME_DBF)
     234           0 :         return MM_DBF_NAME_NO_VALID;
     235             : 
     236       92207 :     for (j = 0; j < mida; j++)
     237             :     {
     238       81935 :         if (!MM_Is_character_valid_for_extended_DBF_field_name(
     239       81935 :                 (unsigned char)nom_camp[j], nullptr))
     240           0 :             return MM_DBF_NAME_NO_VALID;
     241             :     }
     242             : 
     243       10272 :     if (mida >= MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF)
     244        1118 :         return MM_VALID_EXTENDED_DBF_NAME;
     245             : 
     246        9154 :     if (!MM_Is_classical_DBF_field_name_or_lowercase(nom_camp))
     247          32 :         return MM_VALID_EXTENDED_DBF_NAME;
     248             : 
     249        9122 :     if (MM_is_field_name_lowercase(nom_camp))
     250        3327 :         return MM_DBF_NAME_LOWERCASE_AND_VALID;
     251             : 
     252        5795 :     return NM_CLASSICAL_DBF_AND_VALID_NAME;
     253             : }
     254             : 
     255         530 : CPL_DLL MM_BYTE MM_CalculateBytesExtendedFieldName(struct MM_FIELD *camp)
     256             : {
     257         530 :     camp->reserved_2[MM_OFFSET_RESERVED2_EXTENDED_NAME_SIZE] =
     258         530 :         (MM_BYTE)strlen(camp->FieldName);
     259         530 :     return MM_DonaBytesNomEstesCamp(camp);
     260             : }
     261             : 
     262             : static MM_ACCUMULATED_BYTES_TYPE_DBF
     263         194 : MM_CalculateBytesExtendedFieldNames(const struct MM_DATA_BASE_XP *bd_xp)
     264             : {
     265         194 :     MM_ACCUMULATED_BYTES_TYPE_DBF bytes_acumulats = 0;
     266             :     MM_EXT_DBF_N_FIELDS i_camp;
     267             : 
     268        1430 :     for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
     269             :     {
     270        1236 :         if (MM_VALID_EXTENDED_DBF_NAME ==
     271        1236 :             MM_ISExtendedNameBD_XP(bd_xp->pField[i_camp].FieldName))
     272          91 :             bytes_acumulats +=
     273          91 :                 MM_CalculateBytesExtendedFieldName(bd_xp->pField + i_camp);
     274             :     }
     275             : 
     276         194 :     return bytes_acumulats;
     277             : }
     278             : 
     279             : static MM_FIRST_RECORD_OFFSET_TYPE
     280         194 : MM_CalculateBytesFirstRecordOffset(struct MM_DATA_BASE_XP *bd_xp)
     281             : {
     282         194 :     if (bd_xp)
     283         194 :         return (32 + 32 * bd_xp->nFields + 1 +
     284         194 :                 MM_CalculateBytesExtendedFieldNames(bd_xp));
     285           0 :     return 0;
     286             : }
     287             : 
     288         194 : static void MM_CheckDBFHeader(struct MM_DATA_BASE_XP *bd_xp)
     289             : {
     290             :     struct MM_FIELD *camp;
     291             :     MM_EXT_DBF_N_FIELDS i;
     292         194 :     MM_BOOLEAN cal_DBF_estesa = FALSE;
     293             : 
     294         194 :     bd_xp->BytesPerRecord = 1;
     295        1430 :     for (i = 0, camp = bd_xp->pField; i < bd_xp->nFields; i++, camp++)
     296             :     {
     297        1236 :         camp->AccumulatedBytes = bd_xp->BytesPerRecord;
     298        1236 :         bd_xp->BytesPerRecord += camp->BytesPerField;
     299        1236 :         if (camp->DesiredWidth == 0)
     300        1236 :             camp->DesiredWidth = camp->OriginalDesiredWidth =
     301        1236 :                 MM_GetDefaultDesiredDBFFieldWidth(camp);  //camp->BytesPerField;
     302        1236 :         if (camp->FieldType == 'C' &&
     303         192 :             camp->BytesPerField > MM_MAX_AMPLADA_CAMP_C_DBF_CLASSICA)
     304           0 :             cal_DBF_estesa = TRUE;
     305        1236 :         if (MM_VALID_EXTENDED_DBF_NAME ==
     306        1236 :             MM_ISExtendedNameBD_XP(camp->FieldName))
     307          91 :             cal_DBF_estesa = TRUE;
     308             :     }
     309             : 
     310         194 :     bd_xp->FirstRecordOffset = MM_CalculateBytesFirstRecordOffset(bd_xp);
     311             : 
     312         194 :     if (cal_DBF_estesa || bd_xp->nFields > MM_MAX_N_CAMPS_DBF_CLASSICA ||
     313         170 :         bd_xp->nRecords > UINT32_MAX)
     314          24 :         bd_xp->dbf_version = (MM_BYTE)MM_MARCA_VERSIO_1_DBF_ESTESA;
     315             :     else
     316         170 :         bd_xp->dbf_version = MM_MARCA_DBASE4;
     317         194 : }
     318             : 
     319             : static void
     320        2115 : MM_InitializeOffsetExtendedFieldNameFields(struct MM_DATA_BASE_XP *bd_xp,
     321             :                                            MM_EXT_DBF_N_FIELDS i_camp)
     322             : {
     323        2115 :     memset((char *)(&bd_xp->pField[i_camp].reserved_2) +
     324             :                MM_OFFSET_RESERVAT2_OFFSET_NOM_ESTES,
     325             :            0, 4);
     326        2115 : }
     327             : 
     328             : static void
     329        2115 : MM_InitializeBytesExtendedFieldNameFields(struct MM_DATA_BASE_XP *bd_xp,
     330             :                                           MM_EXT_DBF_N_FIELDS i_camp)
     331             : {
     332        2115 :     memset((char *)(&bd_xp->pField[i_camp].reserved_2) +
     333             :                MM_OFFSET_RESERVED2_EXTENDED_NAME_SIZE,
     334             :            0, 1);
     335        2115 : }
     336             : 
     337          91 : static short int MM_return_common_valid_DBF_field_name_string(char *szChain)
     338             : {
     339             :     char *p;
     340          91 :     short int error_retornat = 0;
     341             : 
     342          91 :     if (!szChain)
     343           0 :         return 0;
     344             :     //strupr(szChain);
     345        1204 :     for (p = szChain; *p; p++)
     346             :     {
     347        1113 :         (*p) = (char)toupper((unsigned char)*p);
     348        1113 :         if ((*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_')
     349             :             ;
     350             :         else
     351             :         {
     352           7 :             *p = '_';
     353           7 :             error_retornat |= MM_FIELD_NAME_CHARACTER_INVALID;
     354             :         }
     355             :     }
     356          91 :     if (szChain[0] == '_')
     357             :     {
     358             :         // To avoid having field names starting by '_' this case is
     359             :         // substituted by a 0 (not a '\0').
     360           0 :         szChain[0] = '0';
     361           0 :         error_retornat |= MM_FIELD_NAME_FIRST_CHARACTER_;
     362             :     }
     363          91 :     return error_retornat;
     364             : }
     365             : 
     366          91 : CPL_DLL short int MM_ReturnValidClassicDBFFieldName(char *szChain)
     367             : {
     368             :     size_t long_nom_camp;
     369          91 :     short int error_retornat = 0;
     370             : 
     371          91 :     long_nom_camp = strlen(szChain);
     372          91 :     if ((long_nom_camp < 1) ||
     373             :         (long_nom_camp >= MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF))
     374             :     {
     375          89 :         szChain[MM_MAX_LON_FIELD_NAME_DBF - 1] = '\0';
     376          89 :         error_retornat |= MM_FIELD_NAME_TOO_LONG;
     377             :     }
     378          91 :     error_retornat |= MM_return_common_valid_DBF_field_name_string(szChain);
     379          91 :     return error_retornat;
     380             : }
     381             : 
     382             : static MM_BOOLEAN
     383          91 : MM_CheckClassicFieldNameEqual(const struct MM_DATA_BASE_XP *data_base_XP,
     384             :                               const char *classical_name)
     385             : {
     386             :     MM_EXT_DBF_N_FIELDS i;
     387             : 
     388        1300 :     for (i = 0; i < data_base_XP->nFields; i++)
     389             :     {
     390        1209 :         if ((strcasecmp(data_base_XP->pField[i].ClassicalDBFFieldName,
     391        1209 :                         classical_name)) == 0 ||
     392        1209 :             (strcasecmp(data_base_XP->pField[i].FieldName, classical_name)) ==
     393             :                 0)
     394           0 :             return TRUE;
     395             :     }
     396          91 :     return FALSE;
     397             : }
     398             : 
     399           0 : static char *MM_GiveNewStringWithCharacterInFront(const char *text,
     400             :                                                   char character)
     401             : {
     402             :     char *ptr;
     403             :     size_t i;
     404             : 
     405           0 :     if (!text)
     406           0 :         return nullptr;
     407             : 
     408           0 :     i = strlen(text);
     409           0 :     if ((ptr = VSICalloc(1, i + 2)) == nullptr)
     410           0 :         return nullptr;
     411             : 
     412           0 :     *ptr = character;
     413           0 :     memcpy(ptr + 1, text, i + 1);
     414           0 :     return ptr;
     415             : }
     416             : 
     417           0 : static char *MM_SetSubIndexFieldNam(const char *nom_camp,
     418             :                                     MM_EXT_DBF_N_FIELDS index,
     419             :                                     size_t ampladamax)
     420             : {
     421             :     char *NomCamp_SubIndex;
     422             :     char *_subindex;
     423             :     char subindex[19 + 1];
     424             :     size_t sizet_subindex;
     425             :     size_t sizet_nomcamp;
     426             : 
     427           0 :     NomCamp_SubIndex = VSICalloc(1, ampladamax);
     428           0 :     if (!NomCamp_SubIndex)
     429           0 :         return nullptr;
     430             : 
     431           0 :     CPLStrlcpy(NomCamp_SubIndex, nom_camp, ampladamax);
     432           0 :     NomCamp_SubIndex[ampladamax - 1] = '\0';
     433             : 
     434           0 :     snprintf(subindex, sizeof(subindex), sprintf_UINT64, (GUInt64)index);
     435             : 
     436           0 :     _subindex = MM_GiveNewStringWithCharacterInFront(subindex, '_');
     437           0 :     if (!_subindex)
     438             :     {
     439           0 :         VSIFree(NomCamp_SubIndex);
     440           0 :         return nullptr;
     441             :     }
     442             : 
     443           0 :     sizet_subindex = strlen(_subindex);
     444           0 :     sizet_nomcamp = strlen(NomCamp_SubIndex);
     445             : 
     446           0 :     if (sizet_nomcamp + sizet_subindex > ampladamax - 1)
     447           0 :         memcpy(NomCamp_SubIndex + ((ampladamax - 1) - sizet_subindex),
     448             :                _subindex, strlen(_subindex));
     449             :     else
     450           0 :         NomCamp_SubIndex = strcat(NomCamp_SubIndex, _subindex);
     451             : 
     452           0 :     VSIFree(_subindex);
     453             : 
     454           0 :     return NomCamp_SubIndex;
     455             : }
     456             : 
     457             : CPL_DLL MM_FIRST_RECORD_OFFSET_TYPE
     458         771 : MM_GiveOffsetExtendedFieldName(const struct MM_FIELD *camp)
     459             : {
     460             :     MM_FIRST_RECORD_OFFSET_TYPE offset_nom_camp;
     461             : 
     462         771 :     memcpy(&offset_nom_camp,
     463         771 :            (char *)(&camp->reserved_2) + MM_OFFSET_RESERVAT2_OFFSET_NOM_ESTES,
     464             :            4);
     465         771 :     return offset_nom_camp;
     466             : }
     467             : 
     468         311 : CPL_DLL int MM_WriteNRecordsMMBD_XPFile(struct MM_DATA_BASE_XP *pMMBDXP)
     469             : {
     470         311 :     if (!pMMBDXP || !pMMBDXP->pfDataBase)
     471           0 :         return 0;
     472             : 
     473             :     // Updating number of features in features table
     474         311 :     VSIFSeekL(pMMBDXP->pfDataBase, MM_FIRST_OFFSET_to_N_RECORDS, SEEK_SET);
     475             : 
     476         311 :     if (pMMBDXP->nRecords > UINT32_MAX)
     477             :     {
     478           0 :         pMMBDXP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
     479             :     }
     480             :     else
     481             :     {
     482         311 :         pMMBDXP->dbf_version = MM_MARCA_DBASE4;
     483             :     }
     484             : 
     485             :     {
     486         311 :         GUInt32 nRecords32LowBits = (GUInt32)(pMMBDXP->nRecords & UINT32_MAX);
     487         311 :         if (VSIFWriteL(&nRecords32LowBits, 4, 1, pMMBDXP->pfDataBase) != 1)
     488           0 :             return 1;
     489             :     }
     490             : 
     491         311 :     VSIFSeekL(pMMBDXP->pfDataBase, MM_SECOND_OFFSET_to_N_RECORDS, SEEK_SET);
     492         311 :     if (pMMBDXP->dbf_version == MM_MARCA_VERSIO_1_DBF_ESTESA)
     493             :     {
     494             :         /* from 16 to 19, position MM_SECOND_OFFSET_to_N_RECORDS */
     495           0 :         GUInt32 nRecords32HighBits = (GUInt32)(pMMBDXP->nRecords >> 32);
     496           0 :         if (VSIFWriteL(&nRecords32HighBits, 4, 1, pMMBDXP->pfDataBase) != 1)
     497           0 :             return 1;
     498             : 
     499             :         /* from 20 to 27 */
     500           0 :         if (VSIFWriteL(&(pMMBDXP->dbf_on_a_LAN), 8, 1, pMMBDXP->pfDataBase) !=
     501             :             1)
     502           0 :             return 1;
     503             :     }
     504             :     else
     505             :     {
     506         311 :         if (VSIFWriteL(&(pMMBDXP->dbf_on_a_LAN), 12, 1, pMMBDXP->pfDataBase) !=
     507             :             1)
     508           0 :             return 1;
     509             :     }
     510             : 
     511         311 :     return 0;
     512             : }
     513             : 
     514             : static MM_BOOLEAN
     515         311 : MM_OpenIfNeededAndUpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP)
     516             : {
     517             :     MM_BYTE variable_byte;
     518         311 :     MM_EXT_DBF_N_FIELDS i, j = 0;
     519         311 :     char zero[11] = {0};
     520         311 :     const MM_BYTE byte_zero = 0;
     521         311 :     char ModeLectura_previ[4] = "";
     522             :     MM_FIRST_RECORD_OFFSET_TYPE bytes_acumulats;
     523             :     MM_BYTE name_size;
     524             :     int estat;
     525             :     char nom_camp[MM_MAX_LON_FIELD_NAME_DBF];
     526             :     size_t retorn_fwrite;
     527             : 
     528         311 :     if (!data_base_XP)
     529           0 :         return FALSE;
     530             : 
     531         311 :     if (data_base_XP->pfDataBase == nullptr)
     532             :     {
     533         194 :         strcpy(ModeLectura_previ, data_base_XP->ReadingMode);
     534         194 :         strcpy(data_base_XP->ReadingMode, "wb+");
     535             : 
     536         194 :         if ((data_base_XP->pfDataBase = VSIFOpenL(data_base_XP->szFileName,
     537         194 :                                                   data_base_XP->ReadingMode)) ==
     538             :             nullptr)
     539             :         {
     540           0 :             return FALSE;
     541             :         }
     542             :     }
     543             :     else
     544             :     {
     545             :         // If it's open we just update the header
     546         117 :         VSIFSeekL(data_base_XP->pfDataBase, 0, SEEK_SET);
     547             :     }
     548             : 
     549         311 :     if ((data_base_XP->nFields) > MM_MAX_N_CAMPS_DBF_CLASSICA)
     550           0 :         data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
     551         311 :     else if ((data_base_XP->nRecords) > UINT32_MAX)
     552           0 :         data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
     553             :     else
     554             :     {
     555         311 :         if (data_base_XP->dbf_version == MM_MARCA_VERSIO_1_DBF_ESTESA)
     556          24 :             data_base_XP->dbf_version = MM_MARCA_DBASE4;
     557        2253 :         for (i = 0; i < data_base_XP->nFields; i++)
     558             :         {
     559        2032 :             if (data_base_XP->pField[i].FieldType == 'C' &&
     560         348 :                 data_base_XP->pField[i].BytesPerField >
     561             :                     MM_MAX_AMPLADA_CAMP_C_DBF_CLASSICA)
     562             :             {
     563           0 :                 data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
     564           0 :                 break;
     565             :             }
     566        2032 :             if (MM_VALID_EXTENDED_DBF_NAME ==
     567        2032 :                 MM_ISExtendedNameBD_XP(data_base_XP->pField[i].FieldName))
     568             :             {
     569          90 :                 data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
     570          90 :                 break;
     571             :             }
     572             :         }
     573             :     }
     574             : 
     575             :     // Writing header
     576         311 :     VSIFSeekL(data_base_XP->pfDataBase, 0, SEEK_SET);
     577             : 
     578             :     /* Byte 0 */
     579         311 :     if (VSIFWriteL(&(data_base_XP->dbf_version), 1, 1,
     580             :                    data_base_XP->pfDataBase) != 1)
     581             :     {
     582           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     583           0 :         data_base_XP->pfDataBase = nullptr;
     584           0 :         return FALSE;
     585             :     }
     586             : 
     587             :     /* MM_BYTE from 1 to 3 */
     588         311 :     variable_byte = (MM_BYTE)(data_base_XP->year - 1900);
     589         311 :     if (VSIFWriteL(&variable_byte, 1, 1, data_base_XP->pfDataBase) != 1)
     590             :     {
     591           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     592           0 :         data_base_XP->pfDataBase = nullptr;
     593           0 :         return FALSE;
     594             :     }
     595         311 :     if (VSIFWriteL(&(data_base_XP->month), 1, 1, data_base_XP->pfDataBase) != 1)
     596             :     {
     597           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     598           0 :         data_base_XP->pfDataBase = nullptr;
     599           0 :         return FALSE;
     600             :     }
     601         311 :     if (VSIFWriteL(&(data_base_XP->day), 1, 1, data_base_XP->pfDataBase) != 1)
     602             :     {
     603           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     604           0 :         data_base_XP->pfDataBase = nullptr;
     605           0 :         return FALSE;
     606             :     }
     607             : 
     608             :     /* from 4 a 7, position MM_FIRST_OFFSET_to_N_RECORDS */
     609             :     {
     610         311 :         GUInt32 nRecords32LowBits =
     611         311 :             (GUInt32)(data_base_XP->nRecords & UINT32_MAX);
     612         311 :         if (VSIFWriteL(&nRecords32LowBits, 4, 1, data_base_XP->pfDataBase) != 1)
     613             :         {
     614           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     615           0 :             data_base_XP->pfDataBase = nullptr;
     616           0 :             return FALSE;
     617             :         }
     618             :     }
     619             : 
     620             :     /* from 8 a 9, position MM_PRIMER_OFFSET_a_OFFSET_1a_FITXA */
     621         311 :     if (VSIFWriteL(&(data_base_XP->FirstRecordOffset), 2, 1,
     622             :                    data_base_XP->pfDataBase) != 1)
     623             :     {
     624           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     625           0 :         data_base_XP->pfDataBase = nullptr;
     626           0 :         return FALSE;
     627             :     }
     628             :     /* from 10 to 11, & from 12 to 13 */
     629         311 :     if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version))
     630             :     {
     631          90 :         if (VSIFWriteL(&(data_base_XP->BytesPerRecord),
     632             :                        sizeof(MM_ACCUMULATED_BYTES_TYPE_DBF), 1,
     633             :                        data_base_XP->pfDataBase) != 1)
     634             :         {
     635           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     636           0 :             data_base_XP->pfDataBase = nullptr;
     637           0 :             return FALSE;
     638             :         }
     639             :     }
     640             :     else
     641             :     {
     642             :         /* from 10 to 11 */
     643         221 :         if (VSIFWriteL(&(data_base_XP->BytesPerRecord), 2, 1,
     644             :                        data_base_XP->pfDataBase) != 1)
     645             :         {
     646           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     647           0 :             data_base_XP->pfDataBase = nullptr;
     648           0 :             return FALSE;
     649             :         }
     650             :         /* from 12 to 13 */
     651         221 :         if (VSIFWriteL(&(data_base_XP->reserved_1), 2, 1,
     652             :                        data_base_XP->pfDataBase) != 1)
     653             :         {
     654           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     655           0 :             data_base_XP->pfDataBase = nullptr;
     656           0 :             return FALSE;
     657             :         }
     658             :     }
     659             :     /* byte 14 */
     660         311 :     if (VSIFWriteL(&(data_base_XP->transaction_flag), 1, 1,
     661             :                    data_base_XP->pfDataBase) != 1)
     662             :     {
     663           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     664           0 :         data_base_XP->pfDataBase = nullptr;
     665           0 :         return FALSE;
     666             :     }
     667             :     /* byte 15 */
     668         311 :     if (VSIFWriteL(&(data_base_XP->encryption_flag), 1, 1,
     669             :                    data_base_XP->pfDataBase) != 1)
     670             :     {
     671           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     672           0 :         data_base_XP->pfDataBase = nullptr;
     673           0 :         return FALSE;
     674             :     }
     675             : 
     676             :     /* from 16 to 27 */
     677         311 :     if (data_base_XP->nRecords > UINT32_MAX)
     678             :     {
     679             :         /* from 16 to 19, position MM_SECOND_OFFSET_to_N_RECORDS */
     680           0 :         GUInt32 nRecords32HighBits = (GUInt32)(data_base_XP->nRecords >> 32);
     681           0 :         if (VSIFWriteL(&nRecords32HighBits, 4, 1, data_base_XP->pfDataBase) !=
     682             :             1)
     683             :         {
     684           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     685           0 :             data_base_XP->pfDataBase = nullptr;
     686           0 :             return FALSE;
     687             :         }
     688             : 
     689             :         /* from 20 to 27 */
     690           0 :         if (VSIFWriteL(&(data_base_XP->dbf_on_a_LAN), 8, 1,
     691             :                        data_base_XP->pfDataBase) != 1)
     692             :         {
     693           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     694           0 :             data_base_XP->pfDataBase = nullptr;
     695           0 :             return FALSE;
     696             :         }
     697             :     }
     698             :     else
     699             :     {
     700             :         /* from 16 to 27 */
     701         311 :         if (VSIFWriteL(&(data_base_XP->dbf_on_a_LAN), 12, 1,
     702             :                        data_base_XP->pfDataBase) != 1)
     703             :         {
     704           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     705           0 :             data_base_XP->pfDataBase = nullptr;
     706           0 :             return FALSE;
     707             :         }
     708             :     }
     709             :     /* byte 28 */
     710         311 :     if (VSIFWriteL(&(data_base_XP->MDX_flag), 1, 1, data_base_XP->pfDataBase) !=
     711             :         1)
     712             :     {
     713           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     714           0 :         data_base_XP->pfDataBase = nullptr;
     715           0 :         return FALSE;
     716             :     }
     717             : 
     718             :     /* Byte 29 */
     719         311 :     if (VSIFWriteL(&(data_base_XP->CharSet), 1, 1, data_base_XP->pfDataBase) !=
     720             :         1)
     721             :     {
     722           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     723           0 :         data_base_XP->pfDataBase = nullptr;
     724           0 :         return FALSE;
     725             :     }
     726             : 
     727             :     /* Bytes from 30 to 31, in position MM_SEGON_OFFSET_a_OFFSET_1a_FITXA */
     728         311 :     if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version))
     729             :     {
     730          90 :         if (VSIFWriteL(((char *)&(data_base_XP->FirstRecordOffset)) + 2, 2, 1,
     731             :                        data_base_XP->pfDataBase) != 1)
     732             :         {
     733           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     734           0 :             data_base_XP->pfDataBase = nullptr;
     735           0 :             return FALSE;
     736             :         }
     737             :     }
     738             :     else
     739             :     {
     740         221 :         if (VSIFWriteL(&(data_base_XP->reserved_2), 2, 1,
     741             :                        data_base_XP->pfDataBase) != 1)
     742             :         {
     743           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     744           0 :             data_base_XP->pfDataBase = nullptr;
     745           0 :             return FALSE;
     746             :         }
     747             :     }
     748             : 
     749             :     /* At 32th byte fields description begins   */
     750             :     /* Every description is 32 bytes long       */
     751         311 :     bytes_acumulats = 32 + 32 * (data_base_XP->nFields) + 1;
     752             : 
     753        2865 :     for (i = 0; i < data_base_XP->nFields; i++)
     754             :     {
     755             :         /* Bytes from 0 to 10    -> Field name, \0 finished */
     756        2554 :         estat = MM_ISExtendedNameBD_XP(data_base_XP->pField[i].FieldName);
     757        2554 :         if (estat == NM_CLASSICAL_DBF_AND_VALID_NAME ||
     758             :             estat == MM_DBF_NAME_LOWERCASE_AND_VALID)
     759             :         {
     760        2115 :             j = (short)strlen(data_base_XP->pField[i].FieldName);
     761             : 
     762        2115 :             retorn_fwrite = VSIFWriteL(&data_base_XP->pField[i].FieldName, 1, j,
     763             :                                        data_base_XP->pfDataBase);
     764        2115 :             if (retorn_fwrite != (size_t)j)
     765             :             {
     766           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
     767           0 :                 data_base_XP->pfDataBase = nullptr;
     768           0 :                 return FALSE;
     769             :             }
     770        2115 :             MM_InitializeOffsetExtendedFieldNameFields(data_base_XP, i);
     771        2115 :             MM_InitializeBytesExtendedFieldNameFields(data_base_XP, i);
     772             :         }
     773         439 :         else if (estat == MM_VALID_EXTENDED_DBF_NAME)
     774             :         {
     775         439 :             if (*(data_base_XP->pField[i].ClassicalDBFFieldName) == '\0')
     776             :             {
     777             :                 char nom_temp[MM_MAX_LON_FIELD_NAME_DBF];
     778             : 
     779          91 :                 CPLStrlcpy(nom_temp, data_base_XP->pField[i].FieldName,
     780             :                            MM_MAX_LON_FIELD_NAME_DBF);
     781          91 :                 MM_ReturnValidClassicDBFFieldName(nom_temp);
     782          91 :                 nom_temp[MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF - 1] = '\0';
     783          91 :                 if ((MM_CheckClassicFieldNameEqual(data_base_XP, nom_temp)) ==
     784             :                     TRUE)
     785             :                 {
     786             :                     char *c;
     787             : 
     788           0 :                     c = MM_SetSubIndexFieldNam(
     789             :                         nom_temp, i, MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF);
     790             : 
     791           0 :                     if (c)
     792             :                     {
     793           0 :                         j = 0;
     794           0 :                         while (MM_CheckClassicFieldNameEqual(data_base_XP, c) ==
     795           0 :                                    TRUE &&
     796           0 :                                j < data_base_XP->nFields)
     797             :                         {
     798           0 :                             VSIFree(c);
     799           0 :                             c = MM_SetSubIndexFieldNam(
     800             :                                 nom_temp, ++j,
     801             :                                 MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF);
     802             :                         }
     803           0 :                         if (c)
     804             :                         {
     805           0 :                             CPLStrlcpy(
     806           0 :                                 data_base_XP->pField[i].ClassicalDBFFieldName,
     807             :                                 c,
     808             :                                 sizeof(data_base_XP->pField[i]
     809             :                                            .ClassicalDBFFieldName));
     810           0 :                             VSIFree(c);
     811             :                         }
     812             :                     }
     813             :                 }
     814             :                 else
     815          91 :                     CPLStrlcpy(
     816          91 :                         data_base_XP->pField[i].ClassicalDBFFieldName, nom_temp,
     817             :                         sizeof(data_base_XP->pField[i].ClassicalDBFFieldName));
     818             :             }
     819             : 
     820             :             // This is a 11-byte fixed size field consisting of the filename
     821             :             // and it's been padding calculated some next lines.
     822         439 :             j = (short)strlen(data_base_XP->pField[i].ClassicalDBFFieldName);
     823             : 
     824             :             retorn_fwrite =
     825         439 :                 VSIFWriteL(&data_base_XP->pField[i].ClassicalDBFFieldName, 1, j,
     826             :                            data_base_XP->pfDataBase);
     827         439 :             if (retorn_fwrite != (size_t)j)
     828             :             {
     829           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
     830           0 :                 data_base_XP->pfDataBase = nullptr;
     831           0 :                 return FALSE;
     832             :             }
     833             : 
     834             :             name_size =
     835         439 :                 MM_CalculateBytesExtendedFieldName(data_base_XP->pField + i);
     836         439 :             MM_EscriuOffsetNomEstesBD_XP(data_base_XP, i, bytes_acumulats);
     837         439 :             bytes_acumulats += name_size;
     838             :         }
     839             :         else
     840             :         {
     841           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     842           0 :             data_base_XP->pfDataBase = nullptr;
     843           0 :             return FALSE;
     844             :         }
     845             : 
     846        2554 :         if (VSIFWriteL(zero, 1, 11 - j, data_base_XP->pfDataBase) !=
     847        2554 :             11 - (size_t)j)
     848             :         {
     849           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     850           0 :             data_base_XP->pfDataBase = nullptr;
     851           0 :             return FALSE;
     852             :         }
     853             :         /* Byte 11, Field type */
     854        2554 :         if (VSIFWriteL(&data_base_XP->pField[i].FieldType, 1, 1,
     855             :                        data_base_XP->pfDataBase) != 1)
     856             :         {
     857           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     858           0 :             data_base_XP->pfDataBase = nullptr;
     859           0 :             return FALSE;
     860             :         }
     861             :         /* Bytes 12 to 15 --> Reserved */
     862        2554 :         if (VSIFWriteL(&data_base_XP->pField[i].reserved_1, 4, 1,
     863             :                        data_base_XP->pfDataBase) != 1)
     864             :         {
     865           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     866           0 :             data_base_XP->pfDataBase = nullptr;
     867           0 :             return FALSE;
     868             :         }
     869             :         /* Byte 16, or OFFSET_BYTESxCAMP_CAMP_CLASSIC --> BytesPerField */
     870        2554 :         if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version) &&
     871        1192 :             data_base_XP->pField[i].FieldType == 'C')
     872             :         {
     873         201 :             if (VSIFWriteL((void *)&byte_zero, 1, 1,
     874             :                            data_base_XP->pfDataBase) != 1)
     875             :             {
     876           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
     877           0 :                 data_base_XP->pfDataBase = nullptr;
     878           0 :                 return FALSE;
     879             :             }
     880             :         }
     881             :         else
     882             :         {
     883        2353 :             if (VSIFWriteL(&data_base_XP->pField[i].BytesPerField, 1, 1,
     884             :                            data_base_XP->pfDataBase) != 1)
     885             :             {
     886           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
     887           0 :                 data_base_XP->pfDataBase = nullptr;
     888           0 :                 return FALSE;
     889             :             }
     890             :         }
     891             :         /* 17th byte 17 --> In fields of type 'N' and 'F' indicates decimal places.*/
     892        2554 :         if (data_base_XP->pField[i].FieldType == 'N' ||
     893         716 :             data_base_XP->pField[i].FieldType == 'F')
     894             :         {
     895        1838 :             if (VSIFWriteL(&data_base_XP->pField[i].DecimalsIfFloat, 1, 1,
     896             :                            data_base_XP->pfDataBase) != 1)
     897             :             {
     898           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
     899           0 :                 data_base_XP->pfDataBase = nullptr;
     900           0 :                 return FALSE;
     901             :             }
     902             :         }
     903             :         else
     904             :         {
     905         716 :             if (VSIFWriteL(zero, 1, 1, data_base_XP->pfDataBase) != 1)
     906             :             {
     907           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
     908           0 :                 data_base_XP->pfDataBase = nullptr;
     909           0 :                 return FALSE;
     910             :             }
     911             :         }
     912        2554 :         if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version) &&
     913        1192 :             data_base_XP->pField[i].FieldType == 'C')
     914             :         {
     915             :             /* Bytes from 18 to 20 --> Reserved */
     916         201 :             if (VSIFWriteL(&data_base_XP->pField[i].reserved_2, 20 - 18 + 1, 1,
     917             :                            data_base_XP->pfDataBase) != 1)
     918             :             {
     919           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
     920           0 :                 data_base_XP->pfDataBase = nullptr;
     921           0 :                 return FALSE;
     922             :             }
     923             :             /* Bytes from 21 to 24 --> OFFSET_BYTESxCAMP_CAMP_ESPECIAL, special fields, like C
     924             :                                     in extended DBF */
     925         201 :             if (VSIFWriteL(&data_base_XP->pField[i].BytesPerField,
     926             :                            sizeof(MM_BYTES_PER_FIELD_TYPE_DBF), 1,
     927             :                            data_base_XP->pfDataBase) != 1)
     928             :             {
     929           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
     930           0 :                 data_base_XP->pfDataBase = nullptr;
     931           0 :                 return FALSE;
     932             :             }
     933             : 
     934             :             /* Bytes from 25 to 30 --> Reserved */
     935         201 :             if (VSIFWriteL(&data_base_XP->pField[i].reserved_2[25 - 18],
     936             :                            30 - 25 + 1, 1, data_base_XP->pfDataBase) != 1)
     937             :             {
     938           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
     939           0 :                 data_base_XP->pfDataBase = nullptr;
     940           0 :                 return FALSE;
     941             :             }
     942             :         }
     943             :         else
     944             :         {
     945             :             /* Bytes de 21 a 24 --> OFFSET_BYTESxCAMP_CAMP_ESPECIAL, special fields, like C */
     946        2353 :             memset(data_base_XP->pField[i].reserved_2 +
     947             :                        MM_OFFSET_RESERVAT2_BYTESxCAMP_CAMP_ESPECIAL,
     948             :                    '\0', 4);
     949             :             /* Bytes from 18 to 30 --> Reserved */
     950        2353 :             if (VSIFWriteL(&data_base_XP->pField[i].reserved_2, 13, 1,
     951             :                            data_base_XP->pfDataBase) != 1)
     952             :             {
     953           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
     954           0 :                 data_base_XP->pfDataBase = nullptr;
     955           0 :                 return FALSE;
     956             :             }
     957             :         }
     958             :         /* Byte 31 --> MDX flag.    */
     959        2554 :         if (VSIFWriteL(&data_base_XP->pField[i].MDX_field_flag, 1, 1,
     960             :                        data_base_XP->pfDataBase) != 1)
     961             :         {
     962           0 :             VSIFCloseL(data_base_XP->pfDataBase);
     963           0 :             data_base_XP->pfDataBase = nullptr;
     964           0 :             return FALSE;
     965             :         }
     966             :     }
     967             : 
     968         311 :     variable_byte = 13;
     969         311 :     if (VSIFWriteL(&variable_byte, 1, 1, data_base_XP->pfDataBase) != 1)
     970             :     {
     971           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     972           0 :         data_base_XP->pfDataBase = nullptr;
     973           0 :         return FALSE;
     974             :     }
     975             : 
     976         311 :     if (data_base_XP->FirstRecordOffset != bytes_acumulats)
     977             :     {
     978           0 :         VSIFCloseL(data_base_XP->pfDataBase);
     979           0 :         data_base_XP->pfDataBase = nullptr;
     980           0 :         return FALSE;
     981             :     }
     982             : 
     983             :     // Extended fields
     984        2865 :     for (i = 0; i < data_base_XP->nFields; i++)
     985             :     {
     986        2554 :         if (MM_VALID_EXTENDED_DBF_NAME ==
     987        2554 :             MM_ISExtendedNameBD_XP(data_base_XP->pField[i].FieldName))
     988             :         {
     989         439 :             bytes_acumulats =
     990         439 :                 MM_GiveOffsetExtendedFieldName(data_base_XP->pField + i);
     991         439 :             name_size = MM_DonaBytesNomEstesCamp(data_base_XP->pField + i);
     992             : 
     993         439 :             VSIFSeekL(data_base_XP->pfDataBase, bytes_acumulats, SEEK_SET);
     994             : 
     995         439 :             strcpy(nom_camp, data_base_XP->pField[i].FieldName);
     996             :             //CanviaJocCaracPerEscriureDBF(nom_camp, JocCaracDBFaMM(data_base_XP->CharSet, ParMM.JocCaracDBFPerDefecte));
     997             : 
     998             :             retorn_fwrite =
     999         439 :                 VSIFWriteL(nom_camp, 1, name_size, data_base_XP->pfDataBase);
    1000             : 
    1001         439 :             if (retorn_fwrite != (size_t)name_size)
    1002             :             {
    1003           0 :                 VSIFCloseL(data_base_XP->pfDataBase);
    1004           0 :                 data_base_XP->pfDataBase = nullptr;
    1005           0 :                 return FALSE;
    1006             :             }
    1007             :         }
    1008             :     }
    1009             : 
    1010         311 :     return TRUE;
    1011             : } /* End of MM_OpenIfNeededAndUpdateEntireHeader() */
    1012             : 
    1013         194 : CPL_DLL MM_BOOLEAN MM_CreateAndOpenDBFFile(struct MM_DATA_BASE_XP *bd_xp,
    1014             :                                            const char *NomFitxer)
    1015             : {
    1016             :     time_t currentTime;
    1017             : 
    1018         194 :     if (!NomFitxer || MMIsEmptyString(NomFitxer) || !bd_xp)
    1019           0 :         return FALSE;
    1020             : 
    1021         194 :     MM_CheckDBFHeader(bd_xp);
    1022             : 
    1023             :     // Setting the current date
    1024         194 :     currentTime = time(nullptr);
    1025             : 
    1026             :     struct tm ltime;
    1027         194 :     VSILocalTime(&currentTime, &ltime);
    1028             : 
    1029         194 :     bd_xp->year = (short int)(ltime.tm_year + 1900);
    1030         194 :     bd_xp->month = (MM_BYTE)(ltime.tm_mon + 1);
    1031         194 :     bd_xp->day = (MM_BYTE)ltime.tm_mday;
    1032             : 
    1033         194 :     CPLStrlcpy(bd_xp->szFileName, NomFitxer, sizeof(bd_xp->szFileName));
    1034         194 :     return MM_OpenIfNeededAndUpdateEntireHeader(bd_xp);
    1035             : }
    1036             : 
    1037         338 : CPL_DLL void MM_ReleaseMainFields(struct MM_DATA_BASE_XP *data_base_XP)
    1038             : {
    1039             :     MM_EXT_DBF_N_FIELDS i;
    1040             :     size_t j;
    1041             :     char **szChain;
    1042             : 
    1043         338 :     if (data_base_XP->pField)
    1044             :     {
    1045        2781 :         for (i = 0; i < data_base_XP->nFields; i++)
    1046             :         {
    1047       12220 :             for (j = 0; j < MM_NUM_IDIOMES_MD_MULTIDIOMA; j++)
    1048             :             {
    1049        9776 :                 szChain = data_base_XP->pField[i].Separator;
    1050        9776 :                 if (szChain[j])
    1051             :                 {
    1052           0 :                     VSIFree(szChain[j]);
    1053           0 :                     szChain[j] = nullptr;
    1054             :                 }
    1055             :             }
    1056             :         }
    1057         337 :         VSIFree(data_base_XP->pField);
    1058         337 :         data_base_XP->pField = nullptr;
    1059         337 :         data_base_XP->nFields = 0;
    1060             :     }
    1061         338 :     return;
    1062             : }
    1063             : 
    1064             : // READING THE HEADER OF AN EXTENDED DBF
    1065             : // Free with MM_ReleaseDBFHeader()
    1066         145 : CPL_DLL int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName,
    1067             :                                              struct MM_DATA_BASE_XP *pMMBDXP,
    1068             :                                              const char *pszRelFile)
    1069             : {
    1070             :     MM_BYTE variable_byte;
    1071             :     VSILFILE *pf;
    1072             :     unsigned short int two_bytes;
    1073             :     MM_EXT_DBF_N_FIELDS nIField;
    1074             :     uint16_t offset_primera_fitxa;
    1075         145 :     MM_FIRST_RECORD_OFFSET_TYPE offset_fals = 0;
    1076         145 :     MM_BOOLEAN incoherent_record_size = FALSE;
    1077             :     MM_BYTE un_byte;
    1078             :     MM_BYTES_PER_FIELD_TYPE_DBF bytes_per_camp;
    1079             :     MM_BYTE tretze_bytes[13];
    1080             :     MM_FIRST_RECORD_OFFSET_TYPE offset_possible;
    1081         145 :     MM_BYTE some_problems_when_reading = 0;
    1082         145 :     MM_FILE_OFFSET offset_reintent = 0;  // For retrying
    1083             :     char cpg_file[MM_CPL_PATH_BUF_SIZE];
    1084             :     char *pszDesc;
    1085             :     char section[MM_MAX_LON_FIELD_NAME_DBF + 25];  // TAULA_PRINCIPAL:field_name
    1086             :     GUInt32 nRecords32LowBits;
    1087             :     char *pszString;
    1088             : 
    1089         145 :     if (!szFileName || !pMMBDXP)
    1090           0 :         return 1;
    1091             : 
    1092         145 :     CPLStrlcpy(pMMBDXP->szFileName, szFileName, sizeof(pMMBDXP->szFileName));
    1093         145 :     strcpy(pMMBDXP->ReadingMode, "rb");
    1094             : 
    1095         145 :     if ((pMMBDXP->pfDataBase =
    1096         145 :              VSIFOpenL(pMMBDXP->szFileName, pMMBDXP->ReadingMode)) == nullptr)
    1097           2 :         return 1;
    1098             : 
    1099         143 :     pf = pMMBDXP->pfDataBase;
    1100             : 
    1101         143 :     VSIFSeekL(pf, 0, SEEK_SET);
    1102             :     /* ====== Header reading (32 bytes) =================== */
    1103         143 :     offset_primera_fitxa = 0;
    1104             : 
    1105         286 :     if (1 != VSIFReadL(&(pMMBDXP->dbf_version), 1, 1, pf) ||
    1106         286 :         1 != VSIFReadL(&variable_byte, 1, 1, pf) ||
    1107         286 :         1 != VSIFReadL(&(pMMBDXP->month), 1, 1, pf) ||
    1108         143 :         1 != VSIFReadL(&(pMMBDXP->day), 1, 1, pf))
    1109             :     {
    1110           0 :         fclose_and_nullify(&pMMBDXP->pfDataBase);
    1111           0 :         return 1;
    1112             :     }
    1113             : 
    1114         143 :     if (1 != VSIFReadL(&nRecords32LowBits, 4, 1, pf))
    1115             :     {
    1116           0 :         fclose_and_nullify(&pMMBDXP->pfDataBase);
    1117           0 :         return 1;
    1118             :     }
    1119             : 
    1120         143 :     if (1 != VSIFReadL(&offset_primera_fitxa, 2, 1, pf))
    1121             :     {
    1122           0 :         fclose_and_nullify(&pMMBDXP->pfDataBase);
    1123           0 :         return 1;
    1124             :     }
    1125             : 
    1126         143 :     pMMBDXP->year = (short)(1900 + variable_byte);
    1127         143 : reintenta_lectura_per_si_error_CreaCampBD_XP:
    1128             : 
    1129         143 :     if (some_problems_when_reading > 0)
    1130             :     {
    1131           0 :         if (!MM_ES_DBF_ESTESA(pMMBDXP->dbf_version))
    1132             :         {
    1133           0 :             offset_fals =
    1134           0 :                 offset_primera_fitxa & (MM_FIRST_RECORD_OFFSET_TYPE)(~31);
    1135             :         }
    1136             :     }
    1137             :     else
    1138         143 :         offset_reintent = VSIFTellL(pf);
    1139             : 
    1140         286 :     if (1 != VSIFReadL(&two_bytes, 2, 1, pf) ||
    1141         286 :         1 != VSIFReadL(&(pMMBDXP->reserved_1), 2, 1, pf) ||
    1142         286 :         1 != VSIFReadL(&(pMMBDXP->transaction_flag), 1, 1, pf) ||
    1143         286 :         1 != VSIFReadL(&(pMMBDXP->encryption_flag), 1, 1, pf) ||
    1144         143 :         1 != VSIFReadL(&(pMMBDXP->dbf_on_a_LAN), 12, 1, pf))
    1145             :     {
    1146           0 :         VSIFree(pMMBDXP->pField);
    1147           0 :         pMMBDXP->pField = nullptr;
    1148           0 :         pMMBDXP->nFields = 0;
    1149           0 :         fclose_and_nullify(&pMMBDXP->pfDataBase);
    1150           0 :         return 1;
    1151             :     }
    1152             : 
    1153         143 :     if (MM_ES_DBF_ESTESA(pMMBDXP->dbf_version))
    1154             :     {
    1155             :         GUInt32 nRecords32HighBits;
    1156             : 
    1157             :         // Getting 4 bytes of the 8 bytes variable
    1158          38 :         memcpy(&nRecords32HighBits, &pMMBDXP->dbf_on_a_LAN, 4);
    1159             : 
    1160             :         // Getting other 4 bytes of the 8 bytes variable
    1161             :         // The cast to GUInt64 of the high 32 bits is important to
    1162             :         // make sure the left bit shift is done correctly
    1163          38 :         pMMBDXP->nRecords =
    1164          38 :             ((GUInt64)nRecords32HighBits << 32) | nRecords32LowBits;
    1165             :     }
    1166             :     else
    1167         105 :         pMMBDXP->nRecords = nRecords32LowBits;
    1168             : 
    1169         286 :     if (1 != VSIFReadL(&(pMMBDXP->MDX_flag), 1, 1, pf) ||
    1170         286 :         1 != VSIFReadL(&(pMMBDXP->CharSet), 1, 1, pf) ||
    1171         143 :         1 != VSIFReadL(&(pMMBDXP->reserved_2), 2, 1, pf))
    1172             :     {
    1173           0 :         VSIFree(pMMBDXP->pField);
    1174           0 :         pMMBDXP->pField = nullptr;
    1175           0 :         pMMBDXP->nFields = 0;
    1176           0 :         fclose_and_nullify(&pMMBDXP->pfDataBase);
    1177           0 :         return 1;
    1178             :     }
    1179             : 
    1180             :     // Checking for a cpg file
    1181         143 :     if (pMMBDXP->CharSet == 0)
    1182             :     {
    1183             :         VSILFILE *f_cpg;
    1184             :         char charset_cpg[11];
    1185             : 
    1186           3 :         strcpy(cpg_file, pMMBDXP->szFileName);
    1187           3 :         CPLStrlcpy(cpg_file, CPLResetExtension(cpg_file, "cpg"),
    1188             :                    sizeof(cpg_file));
    1189           3 :         f_cpg = VSIFOpenL(cpg_file, "r");
    1190           3 :         if (f_cpg)
    1191             :         {
    1192             :             char *p;
    1193             :             size_t read_bytes;
    1194           0 :             VSIFSeekL(f_cpg, 0L, SEEK_SET);
    1195           0 :             if (11 > (read_bytes = VSIFReadL(charset_cpg, 1, 10, f_cpg)))
    1196             :             {
    1197           0 :                 charset_cpg[read_bytes] = '\0';
    1198           0 :                 p = MM_stristr(charset_cpg, "UTF-8");
    1199           0 :                 if (p)
    1200           0 :                     pMMBDXP->CharSet = MM_JOC_CARAC_UTF8_DBF;
    1201           0 :                 p = MM_stristr(charset_cpg, "UTF8");
    1202           0 :                 if (p)
    1203           0 :                     pMMBDXP->CharSet = MM_JOC_CARAC_UTF8_DBF;
    1204           0 :                 p = MM_stristr(charset_cpg, "ISO-8859-1");
    1205           0 :                 if (p)
    1206           0 :                     pMMBDXP->CharSet = MM_JOC_CARAC_ANSI_DBASE;
    1207             :             }
    1208           0 :             VSIFCloseL(f_cpg);
    1209             :         }
    1210             :     }
    1211         143 :     if (MM_ES_DBF_ESTESA(pMMBDXP->dbf_version))
    1212             :     {
    1213             :         unsigned short FirstRecordOffsetLow16Bits;
    1214             :         unsigned short FirstRecordOffsetHigh16Bits;
    1215             :         GUInt32 nTmp;
    1216             : 
    1217          38 :         memcpy(&FirstRecordOffsetLow16Bits, &offset_primera_fitxa, 2);
    1218          38 :         memcpy(&FirstRecordOffsetHigh16Bits, &pMMBDXP->reserved_2, 2);
    1219             : 
    1220          38 :         nTmp = ((GUInt32)FirstRecordOffsetHigh16Bits << 16) |
    1221             :                FirstRecordOffsetLow16Bits;
    1222          38 :         if (nTmp > INT32_MAX)
    1223             :         {
    1224           0 :             VSIFree(pMMBDXP->pField);
    1225           0 :             pMMBDXP->pField = nullptr;
    1226           0 :             pMMBDXP->nFields = 0;
    1227           0 :             fclose_and_nullify(&pMMBDXP->pfDataBase);
    1228           0 :             return 1;
    1229             :         }
    1230          38 :         pMMBDXP->FirstRecordOffset = (MM_FIRST_RECORD_OFFSET_TYPE)nTmp;
    1231             : 
    1232          38 :         if (some_problems_when_reading > 0)
    1233           0 :             offset_fals = pMMBDXP->FirstRecordOffset;
    1234             : 
    1235          38 :         memcpy(&FirstRecordOffsetLow16Bits, &two_bytes, 2);
    1236          38 :         memcpy(&FirstRecordOffsetHigh16Bits, &pMMBDXP->reserved_1, 2);
    1237             : 
    1238          38 :         pMMBDXP->BytesPerRecord = ((GUInt32)FirstRecordOffsetHigh16Bits << 16) |
    1239             :                                   FirstRecordOffsetLow16Bits;
    1240             :     }
    1241             :     else
    1242             :     {
    1243         105 :         pMMBDXP->FirstRecordOffset = offset_primera_fitxa;
    1244         105 :         pMMBDXP->BytesPerRecord = two_bytes;
    1245             :     }
    1246             : 
    1247             :     /* ====== Record structure ========================= */
    1248             : 
    1249         143 :     if (some_problems_when_reading > 0)
    1250             :     {
    1251           0 :         if (offset_fals < 1 + 32)
    1252           0 :             pMMBDXP->nFields = 0;
    1253             :         else
    1254           0 :             pMMBDXP->nFields =
    1255           0 :                 (MM_EXT_DBF_N_FIELDS)(((offset_fals - 1) - 32) / 32);
    1256             :     }
    1257             :     else
    1258             :     {
    1259             :         // There's a chance that bytes_acumulats could overflow if it's GUInt32.
    1260             :         // For that reason it's better to promote to GUInt64.
    1261         143 :         GUInt64 bytes_acumulats = 1;
    1262             : 
    1263         143 :         pMMBDXP->nFields = 0;
    1264             : 
    1265         143 :         VSIFSeekL(pf, 0, SEEK_END);
    1266         143 :         if (32 - 1 < VSIFTellL(pf))
    1267             :         {
    1268         143 :             VSIFSeekL(pf, 32, SEEK_SET);
    1269             :             do
    1270             :             {
    1271        1208 :                 bytes_per_camp = 0;
    1272        1208 :                 VSIFSeekL(pf,
    1273        1208 :                           32 + (MM_FILE_OFFSET)pMMBDXP->nFields * 32 +
    1274             :                               (MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF + 1 + 4),
    1275             :                           SEEK_SET);
    1276        2416 :                 if (1 != VSIFReadL(&bytes_per_camp, 1, 1, pf) ||
    1277        2416 :                     1 != VSIFReadL(&un_byte, 1, 1, pf) ||
    1278        1208 :                     1 != VSIFReadL(&tretze_bytes, 3 + sizeof(bytes_per_camp), 1,
    1279             :                                    pf))
    1280             :                 {
    1281           0 :                     VSIFree(pMMBDXP->pField);
    1282           0 :                     pMMBDXP->pField = nullptr;
    1283           0 :                     pMMBDXP->nFields = 0;
    1284           0 :                     fclose_and_nullify(&pMMBDXP->pfDataBase);
    1285           0 :                     return 1;
    1286             :                 }
    1287        1208 :                 if (bytes_per_camp == 0)
    1288          79 :                     memcpy(&bytes_per_camp, (char *)(&tretze_bytes) + 3,
    1289             :                            sizeof(bytes_per_camp));
    1290             : 
    1291        1208 :                 bytes_acumulats += bytes_per_camp;
    1292        1208 :                 pMMBDXP->nFields++;
    1293        1208 :             } while (bytes_acumulats < pMMBDXP->BytesPerRecord);
    1294             :         }
    1295             :     }
    1296             : 
    1297         143 :     if (pMMBDXP->nFields != 0)
    1298             :     {
    1299         143 :         VSIFree(pMMBDXP->pField);
    1300         143 :         pMMBDXP->pField = MM_CreateAllFields(pMMBDXP->nFields);
    1301         143 :         if (!pMMBDXP->pField)
    1302             :         {
    1303           0 :             pMMBDXP->nFields = 0;
    1304           0 :             fclose_and_nullify(&pMMBDXP->pfDataBase);
    1305           0 :             return 1;
    1306             :         }
    1307             :     }
    1308             :     else
    1309             :     {
    1310           0 :         VSIFree(pMMBDXP->pField);
    1311           0 :         pMMBDXP->pField = nullptr;
    1312             :     }
    1313             : 
    1314         143 :     VSIFSeekL(pf, 32, SEEK_SET);
    1315        1351 :     for (nIField = 0; nIField < pMMBDXP->nFields; nIField++)
    1316             :     {
    1317        1208 :         if (1 != VSIFReadL(pMMBDXP->pField[nIField].FieldName,
    1318        1208 :                            MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF, 1, pf) ||
    1319        2416 :             1 != VSIFReadL(&(pMMBDXP->pField[nIField].FieldType), 1, 1, pf) ||
    1320        2416 :             1 != VSIFReadL(&(pMMBDXP->pField[nIField].reserved_1), 4, 1, pf) ||
    1321        1208 :             1 != VSIFReadL(&(pMMBDXP->pField[nIField].BytesPerField), 1, 1,
    1322        1208 :                            pf) ||
    1323        1208 :             1 != VSIFReadL(&(pMMBDXP->pField[nIField].DecimalsIfFloat), 1, 1,
    1324        1208 :                            pf) ||
    1325        2416 :             1 != VSIFReadL(&(pMMBDXP->pField[nIField].reserved_2), 13, 1, pf) ||
    1326             :             1 !=
    1327        1208 :                 VSIFReadL(&(pMMBDXP->pField[nIField].MDX_field_flag), 1, 1, pf))
    1328             :         {
    1329           0 :             VSIFree(pMMBDXP->pField);
    1330           0 :             pMMBDXP->pField = nullptr;
    1331           0 :             pMMBDXP->nFields = 0;
    1332           0 :             VSIFCloseL(pf);
    1333           0 :             pMMBDXP->pfDataBase = nullptr;
    1334           0 :             return 1;
    1335             :         }
    1336             : 
    1337        1208 :         if (pMMBDXP->pField[nIField].FieldType == 'F')
    1338           0 :             pMMBDXP->pField[nIField].FieldType = 'N';
    1339             : 
    1340        1208 :         pMMBDXP->pField[nIField]
    1341        1208 :             .FieldName[MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF - 1] = '\0';
    1342        1208 :         if (EQUAL(pMMBDXP->pField[nIField].FieldName,
    1343             :                   szMMNomCampIdGraficDefecte))
    1344         117 :             pMMBDXP->IdGraficField = nIField;
    1345             : 
    1346             :         // Limit BytesPerField to avoid later integer overflows
    1347             :         // We could potentially limit further...
    1348        1208 :         if (pMMBDXP->pField[nIField].BytesPerField > (uint32_t)(INT32_MAX - 1))
    1349             :         {
    1350           0 :             VSIFree(pMMBDXP->pField);
    1351           0 :             pMMBDXP->pField = nullptr;
    1352           0 :             pMMBDXP->nFields = 0;
    1353           0 :             VSIFCloseL(pf);
    1354           0 :             pMMBDXP->pfDataBase = nullptr;
    1355           0 :             return 1;
    1356             :         }
    1357             : 
    1358        1208 :         if (pMMBDXP->pField[nIField].BytesPerField == 0)
    1359             :         {
    1360          79 :             if (!MM_ES_DBF_ESTESA(pMMBDXP->dbf_version))
    1361             :             {
    1362           0 :                 VSIFree(pMMBDXP->pField);
    1363           0 :                 pMMBDXP->pField = nullptr;
    1364           0 :                 pMMBDXP->nFields = 0;
    1365           0 :                 VSIFCloseL(pf);
    1366           0 :                 pMMBDXP->pfDataBase = nullptr;
    1367           0 :                 return 1;
    1368             :             }
    1369          79 :             if (pMMBDXP->pField[nIField].FieldType != 'C')
    1370             :             {
    1371           0 :                 VSIFree(pMMBDXP->pField);
    1372           0 :                 pMMBDXP->pField = nullptr;
    1373           0 :                 pMMBDXP->nFields = 0;
    1374           0 :                 VSIFCloseL(pf);
    1375           0 :                 pMMBDXP->pfDataBase = nullptr;
    1376           0 :                 return 1;
    1377             :             }
    1378             : 
    1379          79 :             memcpy(&pMMBDXP->pField[nIField].BytesPerField,
    1380          79 :                    (char *)(&pMMBDXP->pField[nIField].reserved_2) + 3,
    1381             :                    sizeof(MM_BYTES_PER_FIELD_TYPE_DBF));
    1382             :         }
    1383             : 
    1384        1208 :         if (nIField)
    1385             :         {
    1386             :             // To avoid overflow
    1387        1065 :             if (pMMBDXP->pField[nIField - 1].AccumulatedBytes >
    1388        1065 :                 UINT32_MAX - pMMBDXP->pField[nIField - 1].BytesPerField)
    1389             :             {
    1390           0 :                 VSIFree(pMMBDXP->pField);
    1391           0 :                 pMMBDXP->pField = nullptr;
    1392           0 :                 pMMBDXP->nFields = 0;
    1393           0 :                 VSIFCloseL(pf);
    1394           0 :                 pMMBDXP->pfDataBase = nullptr;
    1395           0 :                 return 1;
    1396             :             }
    1397             : 
    1398        1065 :             pMMBDXP->pField[nIField].AccumulatedBytes =
    1399        1065 :                 (pMMBDXP->pField[nIField - 1].AccumulatedBytes +
    1400        1065 :                  pMMBDXP->pField[nIField - 1].BytesPerField);
    1401             :         }
    1402             :         else
    1403             :         {
    1404         143 :             pMMBDXP->pField[nIField].AccumulatedBytes = 1;
    1405             :         }
    1406             : 
    1407        1208 :         if (pszRelFile)
    1408             :         {
    1409             :             // Usually, in multilingual MiraMon metadata files, the main
    1410             :             // language is the default one and has no "_cat", "_spa", or
    1411             :             // "_eng" suffix after the keyword. So, to retrieve all
    1412             :             // languages in a multilingual file, first, we'll identify
    1413             :             // the one with no suffix "_cat", "_spa", or "_eng", and then the
    1414             :             // others. If one of them lacks a value, it gets the default value.
    1415        1202 :             snprintf(section, sizeof(section), "TAULA_PRINCIPAL:%s",
    1416        1202 :                      pMMBDXP->pField[nIField].FieldName);
    1417             : 
    1418             :             // MM_DEF_LANGUAGE
    1419        1202 :             pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section,
    1420             :                                                       "descriptor");
    1421        1202 :             if (pszDesc)
    1422             :             {
    1423         632 :                 CPLStrlcpy(
    1424         632 :                     pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE],
    1425             :                     pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1426             : 
    1427         632 :                 VSIFree(pszDesc);
    1428             :             }
    1429             :             else
    1430         570 :                 *pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE] =
    1431             :                     '\0';
    1432             : 
    1433             :             // MM_ENG_LANGUAGE
    1434        1202 :             pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section,
    1435             :                                                       "descriptor_eng");
    1436        1202 :             if (pszDesc)
    1437             :             {
    1438          70 :                 CPLStrlcpy(
    1439          70 :                     pMMBDXP->pField[nIField].FieldDescription[MM_ENG_LANGUAGE],
    1440             :                     pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1441             : 
    1442          70 :                 if (*pMMBDXP->pField[nIField]
    1443             :                          .FieldDescription[MM_DEF_LANGUAGE] == '\0')
    1444             :                 {
    1445           0 :                     CPLStrlcpy(pMMBDXP->pField[nIField]
    1446           0 :                                    .FieldDescription[MM_DEF_LANGUAGE],
    1447             :                                pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1448             :                 }
    1449          70 :                 VSIFree(pszDesc);
    1450             :             }
    1451             :             else
    1452             :             {
    1453             :                 // If there is no value descriptor_eng it's because it's the
    1454             :                 // default one. So, it's taken from there.
    1455        1132 :                 CPLStrlcpy(
    1456        1132 :                     pMMBDXP->pField[nIField].FieldDescription[MM_ENG_LANGUAGE],
    1457        1132 :                     pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE],
    1458             :                     MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1459             :             }
    1460             : 
    1461             :             // MM_CAT_LANGUAGE
    1462        1202 :             pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section,
    1463             :                                                       "descriptor_cat");
    1464        1202 :             if (pszDesc)
    1465             :             {
    1466           0 :                 CPLStrlcpy(
    1467           0 :                     pMMBDXP->pField[nIField].FieldDescription[MM_CAT_LANGUAGE],
    1468             :                     pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1469             : 
    1470           0 :                 if (*pMMBDXP->pField[nIField]
    1471             :                          .FieldDescription[MM_DEF_LANGUAGE] == '\0')
    1472             :                 {
    1473           0 :                     CPLStrlcpy(pMMBDXP->pField[nIField]
    1474           0 :                                    .FieldDescription[MM_DEF_LANGUAGE],
    1475             :                                pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1476             :                 }
    1477             : 
    1478           0 :                 VSIFree(pszDesc);
    1479             :             }
    1480             :             else
    1481             :             {
    1482             :                 // If there is no value descriptor_cat it's because it's the
    1483             :                 // default one. So, it's taken from there.
    1484        1202 :                 CPLStrlcpy(
    1485        1202 :                     pMMBDXP->pField[nIField].FieldDescription[MM_CAT_LANGUAGE],
    1486        1202 :                     pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE],
    1487             :                     MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1488             :             }
    1489             : 
    1490             :             // MM_SPA_LANGUAGE
    1491        1202 :             pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section,
    1492             :                                                       "descriptor_spa");
    1493        1202 :             if (pszDesc)
    1494             :             {
    1495          70 :                 CPLStrlcpy(
    1496          70 :                     pMMBDXP->pField[nIField].FieldDescription[MM_SPA_LANGUAGE],
    1497             :                     pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1498             : 
    1499          70 :                 if (*pMMBDXP->pField[nIField]
    1500             :                          .FieldDescription[MM_DEF_LANGUAGE] == '\0')
    1501             :                 {
    1502           0 :                     CPLStrlcpy(pMMBDXP->pField[nIField]
    1503           0 :                                    .FieldDescription[MM_DEF_LANGUAGE],
    1504             :                                pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1505             :                 }
    1506             : 
    1507          70 :                 VSIFree(pszDesc);
    1508             :             }
    1509             :             else
    1510             :             {
    1511             :                 // If there is no value descriptor_spa it's because it's the
    1512             :                 // default one. So, it's taken from there.
    1513        1132 :                 CPLStrlcpy(
    1514        1132 :                     pMMBDXP->pField[nIField].FieldDescription[MM_SPA_LANGUAGE],
    1515        1132 :                     pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE],
    1516             :                     MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
    1517             :             }
    1518             :         }
    1519             :     }
    1520             : 
    1521         143 :     if (!pMMBDXP->nFields)
    1522             :     {
    1523           0 :         if (pMMBDXP->BytesPerRecord)
    1524           0 :             incoherent_record_size = TRUE;
    1525             :     }
    1526             :     else
    1527             :     {
    1528             :         // To avoid overflow
    1529         143 :         if (pMMBDXP->pField[pMMBDXP->nFields - 1].AccumulatedBytes >
    1530         143 :             UINT32_MAX - pMMBDXP->pField[pMMBDXP->nFields - 1].BytesPerField)
    1531             :         {
    1532           0 :             VSIFree(pMMBDXP->pField);
    1533           0 :             pMMBDXP->pField = nullptr;
    1534           0 :             pMMBDXP->nFields = 0;
    1535           0 :             VSIFCloseL(pf);
    1536           0 :             pMMBDXP->pfDataBase = nullptr;
    1537           0 :             return 1;
    1538             :         }
    1539         143 :         if (pMMBDXP->pField[pMMBDXP->nFields - 1].BytesPerField +
    1540         143 :                 pMMBDXP->pField[pMMBDXP->nFields - 1].AccumulatedBytes >
    1541         143 :             pMMBDXP->BytesPerRecord)
    1542           0 :             incoherent_record_size = TRUE;
    1543             :     }
    1544         143 :     if (incoherent_record_size)
    1545             :     {
    1546           0 :         if (some_problems_when_reading == 0)
    1547             :         {
    1548           0 :             incoherent_record_size = FALSE;
    1549           0 :             VSIFSeekL(pf, offset_reintent, SEEK_SET);
    1550           0 :             some_problems_when_reading++;
    1551             :             /* Reset IdGraficField as it might no longer be valid */
    1552           0 :             pMMBDXP->IdGraficField = 0;
    1553           0 :             goto reintenta_lectura_per_si_error_CreaCampBD_XP;
    1554             :         }
    1555             :         else
    1556             :         {
    1557           0 :             VSIFree(pMMBDXP->pField);
    1558           0 :             pMMBDXP->pField = nullptr;
    1559           0 :             pMMBDXP->nFields = 0;
    1560           0 :             VSIFCloseL(pf);
    1561           0 :             pMMBDXP->pfDataBase = nullptr;
    1562           0 :             return 1;
    1563             :         }
    1564             :     }
    1565             : 
    1566         143 :     offset_possible = 32 + 32 * (pMMBDXP->nFields) + 1;
    1567             : 
    1568         143 :     if (!incoherent_record_size &&
    1569         143 :         offset_possible != pMMBDXP->FirstRecordOffset)
    1570             :     {  // Extended names
    1571             :         MM_FIRST_RECORD_OFFSET_TYPE offset_nom_camp;
    1572             :         int mida_nom;
    1573             : 
    1574         370 :         for (nIField = 0; nIField < pMMBDXP->nFields; nIField++)
    1575             :         {
    1576             :             offset_nom_camp =
    1577         332 :                 MM_GiveOffsetExtendedFieldName(pMMBDXP->pField + nIField);
    1578         332 :             mida_nom = MM_DonaBytesNomEstesCamp(pMMBDXP->pField + nIField);
    1579         332 :             if (mida_nom > 0 && mida_nom < MM_MAX_LON_FIELD_NAME_DBF &&
    1580         101 :                 offset_nom_camp >= offset_possible &&
    1581         101 :                 offset_nom_camp < pMMBDXP->FirstRecordOffset)
    1582             :             {
    1583         101 :                 CPLStrlcpy(pMMBDXP->pField[nIField].ClassicalDBFFieldName,
    1584         101 :                            pMMBDXP->pField[nIField].FieldName,
    1585             :                            MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF);
    1586         101 :                 VSIFSeekL(pf, offset_nom_camp, SEEK_SET);
    1587         101 :                 if (1 != VSIFReadL(pMMBDXP->pField[nIField].FieldName, mida_nom,
    1588             :                                    1, pf))
    1589             :                 {
    1590           0 :                     VSIFree(pMMBDXP->pField);
    1591           0 :                     pMMBDXP->pField = nullptr;
    1592           0 :                     pMMBDXP->nFields = 0;
    1593           0 :                     VSIFCloseL(pf);
    1594           0 :                     pMMBDXP->pfDataBase = nullptr;
    1595           0 :                     return 1;
    1596             :                 }
    1597         101 :                 pMMBDXP->pField[nIField].FieldName[mida_nom] = '\0';
    1598             : 
    1599             :                 // All field names to UTF-8
    1600         101 :                 if (pMMBDXP->CharSet == MM_JOC_CARAC_ANSI_DBASE)
    1601             :                 {
    1602          81 :                     pszString = CPLRecode(pMMBDXP->pField[nIField].FieldName,
    1603             :                                           CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
    1604          81 :                     CPLStrlcpy(pMMBDXP->pField[nIField].FieldName, pszString,
    1605             :                                MM_MAX_LON_FIELD_NAME_DBF);
    1606          81 :                     CPLFree(pszString);
    1607             :                 }
    1608          20 :                 else if (pMMBDXP->CharSet == MM_JOC_CARAC_OEM850_DBASE)
    1609             :                 {
    1610          15 :                     MM_oemansi(pMMBDXP->pField[nIField].FieldName);
    1611          15 :                     pszString = CPLRecode(pMMBDXP->pField[nIField].FieldName,
    1612             :                                           CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
    1613          15 :                     CPLStrlcpy(pMMBDXP->pField[nIField].FieldName, pszString,
    1614             :                                MM_MAX_LON_FIELD_NAME_DBF - 1);
    1615          15 :                     CPLFree(pszString);
    1616             :                 }
    1617             :             }
    1618             :         }
    1619             :     }
    1620             : 
    1621         143 :     pMMBDXP->IdEntityField = MM_MAX_EXT_DBF_N_FIELDS_TYPE;
    1622         143 :     return 0;
    1623             : }  // End of MM_ReadExtendedDBFHeaderFromFile()
    1624             : 
    1625         312 : CPL_DLL void MM_ReleaseDBFHeader(struct MM_DATA_BASE_XP **data_base_XP)
    1626             : {
    1627         312 :     if (!data_base_XP)
    1628           0 :         return;
    1629         312 :     if (!*data_base_XP)
    1630           0 :         return;
    1631             : 
    1632         312 :     MM_ReleaseMainFields(*data_base_XP);
    1633         312 :     VSIFree(*data_base_XP);
    1634         312 :     *data_base_XP = nullptr;
    1635             : 
    1636         312 :     return;
    1637             : }
    1638             : 
    1639         576 : CPL_DLL int MM_ModifyFieldNameAndDescriptorIfPresentBD_XP(
    1640             :     struct MM_FIELD *camp, struct MM_DATA_BASE_XP *bd_xp,
    1641             :     MM_BOOLEAN no_modifica_descriptor, size_t mida_nom)
    1642             : {
    1643             :     MM_EXT_DBF_N_FIELDS i_camp;
    1644         576 :     unsigned n_digits_i = 0, i;
    1645         576 :     int retorn = 0;
    1646             : 
    1647         576 :     if (mida_nom == 0)
    1648         576 :         mida_nom = MM_MAX_LON_FIELD_NAME_DBF;
    1649             : 
    1650        5747 :     for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
    1651             :     {
    1652        5241 :         if (bd_xp->pField + i_camp == camp)
    1653         506 :             continue;
    1654        4735 :         if (!strcasecmp(bd_xp->pField[i_camp].FieldName, camp->FieldName))
    1655          70 :             break;
    1656             :     }
    1657         576 :     if (i_camp < bd_xp->nFields)
    1658             :     {
    1659          70 :         retorn = 1;
    1660          70 :         if (strlen(camp->FieldName) > mida_nom - 2)
    1661           0 :             camp->FieldName[mida_nom - 2] = '\0';
    1662          70 :         strcat(camp->FieldName, "0");
    1663          70 :         for (i = 2; i < (size_t)10; i++)
    1664             :         {
    1665          70 :             snprintf(camp->FieldName + strlen(camp->FieldName) - 1,
    1666          70 :                      sizeof(camp->FieldName) - strlen(camp->FieldName) + 1,
    1667             :                      "%u", i);
    1668         965 :             for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
    1669             :             {
    1670         895 :                 if (bd_xp->pField + i_camp == camp)
    1671          70 :                     continue;
    1672         825 :                 if (!strcasecmp(bd_xp->pField[i_camp].FieldName,
    1673         825 :                                 camp->FieldName))
    1674           0 :                     break;
    1675             :             }
    1676          70 :             if (i_camp == bd_xp->nFields)
    1677             :             {
    1678          70 :                 n_digits_i = 1;
    1679          70 :                 break;
    1680             :             }
    1681             :         }
    1682          70 :         if (i == 10)
    1683             :         {
    1684           0 :             camp->FieldName[strlen(camp->FieldName) - 1] = '\0';
    1685           0 :             if (strlen(camp->FieldName) > mida_nom - 3)
    1686           0 :                 camp->FieldName[mida_nom - 3] = '\0';
    1687           0 :             strcat(camp->FieldName, "00");
    1688           0 :             for (i = 10; i < (size_t)100; i++)
    1689             :             {
    1690           0 :                 snprintf(camp->FieldName + strlen(camp->FieldName) - 2,
    1691           0 :                          sizeof(camp->FieldName) - strlen(camp->FieldName) + 2,
    1692             :                          "%u", i);
    1693           0 :                 for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
    1694             :                 {
    1695           0 :                     if (bd_xp->pField + i_camp == camp)
    1696           0 :                         continue;
    1697           0 :                     if (!strcasecmp(bd_xp->pField[i_camp].FieldName,
    1698           0 :                                     camp->FieldName))
    1699           0 :                         break;
    1700             :                 }
    1701           0 :                 if (i_camp == bd_xp->nFields)
    1702             :                 {
    1703           0 :                     n_digits_i = 2;
    1704           0 :                     break;
    1705             :                 }
    1706             :             }
    1707           0 :             if (i == 100)
    1708             :             {
    1709           0 :                 camp->FieldName[strlen(camp->FieldName) - 2] = '\0';
    1710           0 :                 if (strlen(camp->FieldName) > mida_nom - 4)
    1711           0 :                     camp->FieldName[mida_nom - 4] = '\0';
    1712           0 :                 strcat(camp->FieldName, "000");
    1713           0 :                 for (i = 100; i < (size_t)256 + 2; i++)
    1714             :                 {
    1715           0 :                     snprintf(camp->FieldName + strlen(camp->FieldName) - 3,
    1716           0 :                              sizeof(camp->FieldName) - strlen(camp->FieldName) +
    1717             :                                  3,
    1718             :                              "%u", i);
    1719           0 :                     for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
    1720             :                     {
    1721           0 :                         if (bd_xp->pField + i_camp == camp)
    1722           0 :                             continue;
    1723           0 :                         if (!strcasecmp(bd_xp->pField[i_camp].FieldName,
    1724           0 :                                         camp->FieldName))
    1725           0 :                             break;
    1726             :                     }
    1727           0 :                     if (i_camp == bd_xp->nFields)
    1728             :                     {
    1729           0 :                         n_digits_i = 3;
    1730           0 :                         break;
    1731             :                     }
    1732             :                 }
    1733           0 :                 if (i == 256)
    1734           0 :                     return 2;
    1735             :             }
    1736             :         }
    1737             :     }
    1738             :     else
    1739             :     {
    1740         506 :         i = 1;
    1741             :     }
    1742             : 
    1743         576 :     if ((*(camp->FieldDescription[0]) == '\0') || no_modifica_descriptor)
    1744         477 :         return retorn;
    1745             : 
    1746        1329 :     for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
    1747             :     {
    1748        1230 :         if (bd_xp->pField + i_camp == camp)
    1749          99 :             continue;
    1750        1131 :         if (!strcasecmp(bd_xp->pField[i_camp].FieldDescription[0],
    1751        1131 :                         camp->FieldDescription[0]))
    1752           0 :             break;
    1753             :     }
    1754          99 :     if (i_camp == bd_xp->nFields)
    1755          99 :         return retorn;
    1756             : 
    1757           0 :     if (retorn == 1)
    1758             :     {
    1759           0 :         if (strlen(camp->FieldDescription[0]) >
    1760           0 :             MM_MAX_LON_DESCRIPCIO_CAMP_DBF - 4 - n_digits_i)
    1761           0 :             camp->FieldDescription[0][mida_nom - 4 - n_digits_i] = '\0';
    1762             : 
    1763           0 :         snprintf(camp->FieldDescription[0] + strlen(camp->FieldDescription[0]),
    1764             :                  sizeof(camp->FieldDescription[0]) -
    1765           0 :                      strlen(camp->FieldDescription[0]),
    1766             :                  " (%u)", i);
    1767           0 :         for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
    1768             :         {
    1769           0 :             if (bd_xp->pField + i_camp == camp)
    1770           0 :                 continue;
    1771           0 :             if (!strcasecmp(bd_xp->pField[i_camp].FieldDescription[0],
    1772           0 :                             camp->FieldDescription[0]))
    1773           0 :                 break;
    1774             :         }
    1775           0 :         if (i_camp == bd_xp->nFields)
    1776           0 :             return retorn;
    1777             :     }
    1778             : 
    1779           0 :     retorn = 1;
    1780           0 :     if (strlen(camp->FieldDescription[0]) >
    1781           0 :         MM_MAX_LON_DESCRIPCIO_CAMP_DBF - 4 - n_digits_i)
    1782           0 :         camp->FieldDescription[0][mida_nom - 4 - n_digits_i] = '\0';
    1783           0 :     camp->FieldDescription[0][strlen(camp->FieldDescription[0]) - 4 -
    1784           0 :                               n_digits_i + 1] = '\0';
    1785           0 :     if (strlen(camp->FieldDescription[0]) > MM_MAX_LON_DESCRIPCIO_CAMP_DBF - 7)
    1786           0 :         camp->FieldDescription[0][mida_nom - 7] = '\0';
    1787           0 :     for (i++; i < (size_t)256; i++)
    1788             :     {
    1789             :         //if (camp->FieldDescription[0] + strlen(camp->FieldDescription[0]))
    1790           0 :         snprintf(camp->FieldDescription[0] + strlen(camp->FieldDescription[0]),
    1791             :                  sizeof(camp->FieldDescription[0]) -
    1792           0 :                      strlen(camp->FieldDescription[0]),
    1793             :                  " (%u)", i);
    1794           0 :         for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
    1795             :         {
    1796           0 :             if (bd_xp->pField + i_camp == camp)
    1797           0 :                 continue;
    1798           0 :             if (!strcasecmp(bd_xp->pField[i_camp].FieldName, camp->FieldName))
    1799           0 :                 break;
    1800             :         }
    1801           0 :         if (i_camp == bd_xp->nFields)
    1802           0 :             return retorn;
    1803             :     }
    1804           0 :     return 2;
    1805             : }  // End of MM_ModifyFieldNameAndDescriptorIfPresentBD_XP()
    1806             : 
    1807         576 : static int MM_DuplicateMultilingualString(
    1808             :     char *(szChain_final[MM_NUM_IDIOMES_MD_MULTIDIOMA]),
    1809             :     const char *const(szChain_inicial[MM_NUM_IDIOMES_MD_MULTIDIOMA]))
    1810             : {
    1811             :     size_t i;
    1812             : 
    1813        2880 :     for (i = 0; i < MM_NUM_IDIOMES_MD_MULTIDIOMA; i++)
    1814             :     {
    1815        2304 :         if (szChain_inicial[i])
    1816             :         {
    1817           0 :             if (nullptr == (szChain_final[i] = strdup(szChain_inicial[i])))
    1818           0 :                 return 1;
    1819             :         }
    1820             :         else
    1821        2304 :             szChain_final[i] = nullptr;
    1822             :     }
    1823         576 :     return 0;
    1824             : }
    1825             : 
    1826         576 : CPL_DLL int MM_DuplicateFieldDBXP(struct MM_FIELD *camp_final,
    1827             :                                   const struct MM_FIELD *camp_inicial)
    1828             : {
    1829         576 :     *camp_final = *camp_inicial;
    1830             : 
    1831         576 :     if (0 != MM_DuplicateMultilingualString(
    1832         576 :                  camp_final->Separator,
    1833         576 :                  (const char *const(*))camp_inicial->Separator))
    1834           0 :         return 1;
    1835             : 
    1836         576 :     return 0;
    1837             : }
    1838             : 
    1839             : // If n_bytes==SIZE_MAX, the parameter is ignored ant, then,
    1840             : // it's assumed that szszChain is NUL terminated
    1841        2715 : CPL_DLL char *MM_oemansi_n(char *szszChain, size_t n_bytes)
    1842             : {
    1843             :     size_t u_i;
    1844             :     unsigned char *punter_bait;
    1845        2715 :     unsigned char t_oemansi[128] = {
    1846             :         199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232, 239, 238,
    1847             :         236, 196, 197, 201, 230, 198, 244, 246, 242, 251, 249, 255, 214,
    1848             :         220, 248, 163, 216, 215, 131, 225, 237, 243, 250, 241, 209, 170,
    1849             :         186, 191, 174, 172, 189, 188, 161, 171, 187, 164, 164, 164, 166,
    1850             :         166, 193, 194, 192, 169, 166, 166, 164, 164, 162, 165, 164, 164,
    1851             :         164, 164, 164, 164, 164, 227, 195, 164, 164, 164, 164, 166, 164,
    1852             :         164, 164, 240, 208, 202, 203, 200, 180, 205, 206, 207, 164, 164,
    1853             :         164, 164, 166, 204, 164, 211, 223, 212, 210, 245, 213, 181, 254,
    1854             :         222, 218, 219, 217, 253, 221, 175, 180, 173, 177, 164, 190, 182,
    1855             :         167, 247, 184, 176, 168, 183, 185, 179, 178, 164, 183};
    1856        2715 :     if (n_bytes == SIZE_MAX)
    1857             :     {
    1858       27997 :         for (punter_bait = (unsigned char *)szszChain; *punter_bait;
    1859       25430 :              punter_bait++)
    1860             :         {
    1861       25430 :             if (*punter_bait > 127)
    1862         310 :                 *punter_bait = t_oemansi[*punter_bait - 128];
    1863             :         }
    1864             :     }
    1865             :     else
    1866             :     {
    1867        2056 :         for (u_i = 0, punter_bait = (unsigned char *)szszChain; u_i < n_bytes;
    1868        1908 :              punter_bait++, u_i++)
    1869             :         {
    1870        1908 :             if (*punter_bait > 127)
    1871           0 :                 *punter_bait = t_oemansi[*punter_bait - 128];
    1872             :         }
    1873             :     }
    1874        2715 :     return szszChain;
    1875             : }
    1876             : 
    1877             : // An implementation of non-sensitive strstr()
    1878        1406 : CPL_DLL char *MM_stristr(const char *haystack, const char *needle)
    1879             : {
    1880        1406 :     if (!haystack)
    1881           0 :         return nullptr;
    1882             : 
    1883        1406 :     if (!needle)
    1884           0 :         return nullptr;
    1885             : 
    1886        1406 :     if (!*needle)
    1887           0 :         return (char *)haystack;
    1888             : 
    1889        1406 :     char *p1 = (char *)haystack;
    1890       28759 :     while (*p1 != '\0' && !EQUALN(p1, needle, strlen(needle)))
    1891       27353 :         p1++;
    1892             : 
    1893        1406 :     if (*p1 == '\0')
    1894         501 :         return nullptr;
    1895             : 
    1896         905 :     return p1;
    1897             : }
    1898             : 
    1899        2567 : CPL_DLL char *MM_oemansi(char *szszChain)
    1900             : {
    1901        2567 :     return MM_oemansi_n(szszChain, SIZE_MAX);
    1902             : }
    1903             : 
    1904             : CPL_DLL int
    1905        1333 : MM_SecureCopyStringFieldValue(char **pszStringDst, const char *pszStringSrc,
    1906             :                               MM_EXT_DBF_N_FIELDS *nStringCurrentLength)
    1907             : {
    1908             : 
    1909        1333 :     if (!pszStringSrc)
    1910             :     {
    1911           0 :         if (1 >= *nStringCurrentLength)
    1912             :         {
    1913           0 :             void *new_ptr = VSIRealloc(*pszStringDst, 2);
    1914           0 :             if (!new_ptr)
    1915           0 :                 return 1;
    1916           0 :             *pszStringDst = new_ptr;
    1917           0 :             *nStringCurrentLength = (MM_EXT_DBF_N_FIELDS)2;
    1918             :         }
    1919           0 :         strcpy(*pszStringDst, "\0");
    1920           0 :         return 0;
    1921             :     }
    1922             : 
    1923        1333 :     if (strlen(pszStringSrc) >= *nStringCurrentLength)
    1924             :     {
    1925         446 :         void *new_ptr = VSIRealloc(*pszStringDst, strlen(pszStringSrc) + 1);
    1926         446 :         if (!new_ptr)
    1927           0 :             return 1;
    1928         446 :         (*pszStringDst) = new_ptr;
    1929         446 :         *nStringCurrentLength = (MM_EXT_DBF_N_FIELDS)(strlen(pszStringSrc) + 1);
    1930             :     }
    1931        1333 :     strcpy(*pszStringDst, pszStringSrc);
    1932        1333 :     return 0;
    1933             : }
    1934             : 
    1935             : // This function assumes that all the file is saved in disk and closed.
    1936         117 : CPL_DLL int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP,
    1937             :                                    MM_EXT_DBF_N_FIELDS nIField,
    1938             :                                    MM_BYTES_PER_FIELD_TYPE_DBF nNewWidth,
    1939             :                                    MM_BYTE nNewPrecision)
    1940             : {
    1941         117 :     char *record, *whites = nullptr;
    1942             :     MM_BYTES_PER_FIELD_TYPE_DBF l_glop1, l_glop2, i_glop2;
    1943             :     MM_EXT_DBF_N_RECORDS nfitx, i_reg;
    1944             :     int canvi_amplada;  // change width
    1945             :     GInt32 j;
    1946             :     MM_EXT_DBF_N_FIELDS i_camp;
    1947             :     size_t retorn_fwrite;
    1948             :     int retorn_TruncaFitxer;
    1949             : 
    1950         117 :     if (!data_base_XP)
    1951           0 :         return 1;
    1952             : 
    1953         117 :     canvi_amplada = nNewWidth - data_base_XP->pField[nIField].BytesPerField;
    1954             : 
    1955         117 :     if (data_base_XP->nRecords != 0)
    1956             :     {
    1957          48 :         l_glop1 = data_base_XP->pField[nIField].AccumulatedBytes;
    1958          48 :         i_glop2 = l_glop1 + data_base_XP->pField[nIField].BytesPerField;
    1959          48 :         if (nIField == data_base_XP->nFields - 1)
    1960          26 :             l_glop2 = 0;
    1961             :         else
    1962          22 :             l_glop2 = data_base_XP->BytesPerRecord -
    1963          22 :                       data_base_XP->pField[nIField + 1].AccumulatedBytes;
    1964             : 
    1965          48 :         if ((record = VSICalloc(1, (size_t)data_base_XP->BytesPerRecord)) ==
    1966             :             nullptr)
    1967           0 :             return 1;
    1968             : 
    1969          48 :         record[data_base_XP->BytesPerRecord - 1] = MM_SetEndOfString;
    1970             : 
    1971          48 :         if ((whites = (char *)VSICalloc(1, (size_t)nNewWidth)) == nullptr)
    1972             :         {
    1973           0 :             VSIFree(record);
    1974           0 :             return 1;
    1975             :         }
    1976          48 :         memset(whites, ' ', nNewWidth);
    1977             : 
    1978          48 :         nfitx = data_base_XP->nRecords;
    1979          48 :         i_reg = (canvi_amplada < 0 ? 0 : nfitx - 1);
    1980             :         while (TRUE)
    1981             :         {
    1982          48 :             if (0 != VSIFSeekL(data_base_XP->pfDataBase,
    1983          48 :                                data_base_XP->FirstRecordOffset +
    1984          48 :                                    (MM_FILE_OFFSET)i_reg *
    1985          48 :                                        data_base_XP->BytesPerRecord,
    1986             :                                SEEK_SET))
    1987             :             {
    1988           0 :                 VSIFree(whites);
    1989           0 :                 VSIFree(record);
    1990           0 :                 return 1;
    1991             :             }
    1992             : 
    1993          48 :             if (1 != VSIFReadL(record, data_base_XP->BytesPerRecord, 1,
    1994             :                                data_base_XP->pfDataBase))
    1995             :             {
    1996           0 :                 VSIFree(whites);
    1997           0 :                 VSIFree(record);
    1998           0 :                 return 1;
    1999             :             }
    2000             : 
    2001          48 :             if (0 !=
    2002          48 :                 VSIFSeekL(
    2003             :                     data_base_XP->pfDataBase,
    2004          48 :                     (MM_FILE_OFFSET)data_base_XP->FirstRecordOffset +
    2005          48 :                         i_reg * ((MM_FILE_OFFSET)data_base_XP->BytesPerRecord +
    2006             :                                  canvi_amplada),
    2007             :                     SEEK_SET))
    2008             :             {
    2009           0 :                 VSIFree(whites);
    2010           0 :                 VSIFree(record);
    2011           0 :                 return 1;
    2012             :             }
    2013             : 
    2014          48 :             if (1 != VSIFWriteL(record, l_glop1, 1, data_base_XP->pfDataBase))
    2015             :             {
    2016           0 :                 VSIFree(whites);
    2017           0 :                 VSIFree(record);
    2018           0 :                 return 1;
    2019             :             }
    2020             : 
    2021          48 :             switch (data_base_XP->pField[nIField].FieldType)
    2022             :             {
    2023          30 :                 case 'C':
    2024             :                 case 'L':
    2025          30 :                     memcpy(whites, record + l_glop1,
    2026             :                            (canvi_amplada < 0
    2027             :                                 ? nNewWidth
    2028          30 :                                 : data_base_XP->pField[nIField].BytesPerField));
    2029          30 :                     retorn_fwrite = VSIFWriteL(whites, nNewWidth, 1,
    2030             :                                                data_base_XP->pfDataBase);
    2031             : 
    2032          30 :                     if (1 != retorn_fwrite)
    2033             :                     {
    2034           0 :                         VSIFree(whites);
    2035           0 :                         VSIFree(record);
    2036           0 :                         return 1;
    2037             :                     }
    2038          30 :                     break;
    2039          18 :                 case 'N':
    2040             : 
    2041          18 :                     if (canvi_amplada >= 0)
    2042             :                     {
    2043          18 :                         if (1 != VSIFWriteL(whites, canvi_amplada, 1,
    2044          18 :                                             data_base_XP->pfDataBase) ||
    2045             :                             1 !=
    2046          18 :                                 VSIFWriteL(
    2047          18 :                                     record + l_glop1,
    2048          18 :                                     data_base_XP->pField[nIField].BytesPerField,
    2049             :                                     1, data_base_XP->pfDataBase))
    2050             :                         {
    2051           0 :                             VSIFree(whites);
    2052           0 :                             VSIFree(record);
    2053           0 :                             return 1;
    2054             :                         }
    2055             :                     }
    2056           0 :                     else if (canvi_amplada < 0)
    2057             :                     {
    2058           0 :                         j = (GInt32)(l_glop1 + (data_base_XP->pField[nIField]
    2059           0 :                                                     .BytesPerField -
    2060             :                                                 1));
    2061             :                         while (TRUE)
    2062             :                         {
    2063           0 :                             j--;
    2064             : 
    2065           0 :                             if (j < (GInt32)l_glop1 || record[j] == ' ')
    2066             :                             {
    2067           0 :                                 j++;
    2068           0 :                                 break;
    2069             :                             }
    2070             :                         }
    2071             : 
    2072           0 :                         if ((data_base_XP->pField[nIField].BytesPerField +
    2073           0 :                              l_glop1 - j) < nNewWidth)
    2074           0 :                             j -= (GInt32)(nNewWidth -
    2075           0 :                                           (data_base_XP->pField[nIField]
    2076           0 :                                                .BytesPerField +
    2077             :                                            l_glop1 - j));
    2078             : 
    2079           0 :                         retorn_fwrite = VSIFWriteL(record + j, nNewWidth, 1,
    2080             :                                                    data_base_XP->pfDataBase);
    2081           0 :                         if (1 != retorn_fwrite)
    2082             :                         {
    2083           0 :                             VSIFree(whites);
    2084           0 :                             VSIFree(record);
    2085           0 :                             return 1;
    2086             :                         }
    2087             :                     }
    2088             : 
    2089          18 :                     break;
    2090           0 :                 default:
    2091           0 :                     VSIFree(whites);
    2092           0 :                     VSIFree(record);
    2093           0 :                     return 1;
    2094             :             }
    2095          48 :             if (l_glop2)
    2096             :             {
    2097          22 :                 retorn_fwrite = VSIFWriteL(record + i_glop2, l_glop2, 1,
    2098             :                                            data_base_XP->pfDataBase);
    2099          22 :                 if (1 != retorn_fwrite)
    2100             :                 {
    2101           0 :                     VSIFree(whites);
    2102           0 :                     VSIFree(record);
    2103           0 :                     return 1;
    2104             :                 }
    2105             :             }
    2106             : 
    2107          48 :             if (canvi_amplada < 0)
    2108             :             {
    2109           0 :                 if (i_reg + 1 == nfitx)
    2110           0 :                     break;
    2111           0 :                 i_reg++;
    2112             :             }
    2113             :             else
    2114             :             {
    2115          48 :                 if (i_reg == 0)
    2116          48 :                     break;
    2117           0 :                 i_reg--;
    2118             :             }
    2119             :         }
    2120             : 
    2121          48 :         VSIFree(whites);
    2122          48 :         VSIFree(record);
    2123             : 
    2124          48 :         retorn_TruncaFitxer = VSIFTruncateL(
    2125             :             data_base_XP->pfDataBase,
    2126          48 :             (MM_FILE_OFFSET)data_base_XP->FirstRecordOffset +
    2127          48 :                 (MM_FILE_OFFSET)data_base_XP->nRecords *
    2128          48 :                     ((MM_FILE_OFFSET)data_base_XP->BytesPerRecord +
    2129             :                      canvi_amplada));
    2130          48 :         if (canvi_amplada < 0 && retorn_TruncaFitxer)
    2131           0 :             return 1;
    2132             :     } /* Fi de registres de != 0*/
    2133             : 
    2134         117 :     if (canvi_amplada != 0)
    2135             :     {
    2136         117 :         data_base_XP->pField[nIField].BytesPerField = nNewWidth;
    2137         117 :         data_base_XP->BytesPerRecord += canvi_amplada;
    2138         117 :         for (i_camp = (MM_EXT_DBF_N_FIELDS)(nIField + 1);
    2139         477 :              i_camp < data_base_XP->nFields; i_camp++)
    2140         360 :             data_base_XP->pField[i_camp].AccumulatedBytes += canvi_amplada;
    2141             :     }
    2142         117 :     data_base_XP->pField[nIField].DecimalsIfFloat = nNewPrecision;
    2143             : 
    2144         117 :     if ((MM_OpenIfNeededAndUpdateEntireHeader(data_base_XP)) == FALSE)
    2145           0 :         return 1;
    2146             : 
    2147         117 :     return 0;
    2148             : } /* End of MMChangeCFieldWidthDBF() */
    2149             : 
    2150       15872 : static char *MM_l_RemoveWhitespacesFromEndOfString(char *punter,
    2151             :                                                    size_t l_szChain)
    2152             : {
    2153       15872 :     size_t longitud_szChain = l_szChain;
    2154       35838 :     while (longitud_szChain > 0)
    2155             :     {
    2156       35414 :         longitud_szChain--;
    2157       35414 :         if (punter[longitud_szChain] != ' ' && punter[longitud_szChain] != '\t')
    2158             :         {
    2159       15448 :             break;
    2160             :         }
    2161       19966 :         punter[longitud_szChain] = '\0';
    2162             :     }
    2163       15872 :     return punter;
    2164             : }
    2165             : 
    2166          50 : CPL_DLL char *MM_RemoveInitial_and_FinalQuotationMarks(char *szChain)
    2167             : {
    2168             :     char *ptr1, *ptr2;
    2169          50 :     char cometa = '"';
    2170             : 
    2171          50 :     if (*szChain == cometa)
    2172             :     {
    2173          11 :         ptr1 = szChain;
    2174          11 :         ptr2 = ptr1 + 1;
    2175          11 :         if (*ptr2)
    2176             :         {
    2177         182 :             while (*ptr2)
    2178             :             {
    2179         171 :                 *ptr1 = *ptr2;
    2180         171 :                 ptr1++;
    2181         171 :                 ptr2++;
    2182             :             }
    2183          11 :             if (*ptr1 == cometa)
    2184          11 :                 *(ptr1 - 1) = 0;
    2185             :             else
    2186           0 :                 *ptr1 = 0;
    2187             :         }
    2188             :     }
    2189          50 :     return szChain;
    2190             : } /* End of MM_RemoveInitial_and_FinalQuotationMarks() */
    2191             : 
    2192          84 : CPL_DLL char *MM_RemoveLeadingWhitespaceOfString(char *szChain)
    2193             : {
    2194             :     char *ptr;
    2195             :     char *ptr2;
    2196             : 
    2197          84 :     if (szChain == nullptr)
    2198           0 :         return szChain;
    2199             : 
    2200         630 :     for (ptr = szChain; *ptr && (*ptr == ' ' || *ptr == '\t'); ptr++)
    2201         546 :         continue;
    2202             : 
    2203          84 :     if (ptr != szChain)
    2204             :     {
    2205          66 :         ptr2 = szChain;
    2206         534 :         while (*ptr)
    2207             :         {
    2208         468 :             *ptr2 = *ptr;
    2209         468 :             ptr2++;
    2210         468 :             ptr++;
    2211             :         }
    2212          66 :         *ptr2 = 0;
    2213             :     }
    2214          84 :     return szChain;
    2215             : }
    2216             : 
    2217             : // Checks if a string is empty
    2218        6460 : CPL_DLL int MMIsEmptyString(const char *string)
    2219             : {
    2220        6460 :     const char *ptr = string;
    2221             : 
    2222       15105 :     for (; *ptr; ptr++)
    2223       14420 :         if (*ptr != ' ' && *ptr != '\t')
    2224        5775 :             return 0;
    2225             : 
    2226         685 :     return 1;
    2227             : }
    2228             : 
    2229       15872 : CPL_DLL char *MM_RemoveWhitespacesFromEndOfString(char *str)
    2230             : {
    2231       15872 :     if (str == nullptr)
    2232           0 :         return str;
    2233       15872 :     return MM_l_RemoveWhitespacesFromEndOfString(str, strlen(str));
    2234             : }
    2235             : 
    2236         113 : CPL_DLL struct MM_ID_GRAFIC_MULTIPLE_RECORD *MMCreateExtendedDBFIndex(
    2237             :     VSILFILE *f, MM_EXT_DBF_N_RECORDS nNumberOfRecords,
    2238             :     MM_FIRST_RECORD_OFFSET_TYPE offset_1era,
    2239             :     MM_ACCUMULATED_BYTES_TYPE_DBF bytes_per_fitxa,
    2240             :     MM_ACCUMULATED_BYTES_TYPE_DBF bytes_acumulats_id_grafic,
    2241             :     MM_BYTES_PER_FIELD_TYPE_DBF bytes_id_grafic, MM_BOOLEAN *isListField,
    2242             :     MM_EXT_DBF_N_RECORDS *nMaxN)
    2243             : {
    2244             :     struct MM_ID_GRAFIC_MULTIPLE_RECORD *id;
    2245             :     MM_EXT_DBF_N_RECORDS i_dbf;
    2246             :     MM_EXT_DBF_SIGNED_N_RECORDS i, id_grafic;
    2247             :     char *fitxa;
    2248         113 :     MM_BYTES_PER_FIELD_TYPE_DBF bytes_final_id_principi_id1 =
    2249             :         bytes_per_fitxa - bytes_id_grafic;
    2250             : 
    2251         113 :     *isListField = FALSE;
    2252         113 :     *nMaxN = 0;
    2253         113 :     if (!nNumberOfRecords)
    2254           9 :         return nullptr;  // No elements to read
    2255             : 
    2256         104 :     if (MMCheckSize_t(nNumberOfRecords, sizeof(*id)))
    2257           0 :         return nullptr;
    2258         104 :     if (nullptr == (id = (struct MM_ID_GRAFIC_MULTIPLE_RECORD *)VSICalloc(
    2259             :                         (size_t)nNumberOfRecords, sizeof(*id))))
    2260           0 :         return nullptr;
    2261             : 
    2262         104 :     if (bytes_id_grafic == UINT32_MAX)
    2263             :     {
    2264           0 :         VSIFree(id);
    2265           0 :         CPLError(CE_Failure, CPLE_OutOfMemory, "Overflow in bytes_id_graphic");
    2266           0 :         return nullptr;
    2267             :     }
    2268             : 
    2269         104 :     if (nullptr == (fitxa = (char *)VSICalloc(1, (size_t)bytes_id_grafic + 1)))
    2270             :     {
    2271           0 :         VSIFree(id);
    2272           0 :         return nullptr;
    2273             :     }
    2274         104 :     fitxa[bytes_id_grafic] = '\0';
    2275             : 
    2276         104 :     VSIFSeekL(f,
    2277         104 :               (MM_FILE_OFFSET)offset_1era +
    2278         104 :                   (MM_FILE_OFFSET)bytes_acumulats_id_grafic,
    2279             :               SEEK_SET);
    2280             : 
    2281         104 :     i_dbf = 0;
    2282             :     do
    2283             :     {
    2284         104 :         if (i_dbf == nNumberOfRecords ||
    2285         104 :             VSIFReadL(fitxa, 1, bytes_id_grafic, f) != (size_t)bytes_id_grafic)
    2286             :         {
    2287           0 :             VSIFree(id);
    2288           0 :             VSIFree(fitxa);
    2289           0 :             return nullptr;
    2290             :         }
    2291         104 :         i_dbf++;
    2292             :     } while (1 !=
    2293         208 :                  sscanf(fitxa, scanf_MM_EXT_DBF_SIGNED_N_RECORDS, &id_grafic) ||
    2294         104 :              id_grafic < 0);
    2295         104 :     i = 0;
    2296             : 
    2297             :     while (TRUE)
    2298             :     {
    2299         560 :         if (i > id_grafic)
    2300             :         {
    2301           0 :             VSIFree(id);
    2302           0 :             VSIFree(fitxa);
    2303           0 :             return nullptr;
    2304             :         }
    2305         560 :         i = id_grafic;
    2306         560 :         if (i >= (MM_EXT_DBF_SIGNED_N_RECORDS)nNumberOfRecords)
    2307             :         {
    2308           0 :             VSIFree(fitxa);
    2309           0 :             return id;
    2310             :         }
    2311         560 :         id[(size_t)i].offset = (MM_FILE_OFFSET)offset_1era +
    2312         560 :                                (MM_FILE_OFFSET)(i_dbf - 1) * bytes_per_fitxa;
    2313             :         do
    2314             :         {
    2315         602 :             id[(size_t)i].nMR++;
    2316         602 :             if (!(*isListField) && id[(size_t)i].nMR > 1)
    2317          33 :                 *isListField = TRUE;
    2318         602 :             if (*nMaxN < id[(size_t)i].nMR)
    2319         141 :                 *nMaxN = id[(size_t)i].nMR;
    2320             : 
    2321         602 :             if (i_dbf == nNumberOfRecords)
    2322             :             {
    2323         104 :                 VSIFree(fitxa);
    2324         104 :                 return id;
    2325             :             }
    2326         498 :             VSIFSeekL(f, bytes_final_id_principi_id1, SEEK_CUR);
    2327         498 :             if (VSIFReadL(fitxa, 1, bytes_id_grafic, f) !=
    2328             :                 (size_t)bytes_id_grafic)
    2329             :             {
    2330           0 :                 VSIFree(id);
    2331           0 :                 VSIFree(fitxa);
    2332           0 :                 return nullptr;
    2333             :             }
    2334         498 :             if (1 != sscanf(fitxa, scanf_MM_EXT_DBF_SIGNED_N_RECORDS,
    2335         498 :                             &id_grafic) ||
    2336         498 :                 id_grafic >= (MM_EXT_DBF_SIGNED_N_RECORDS)nNumberOfRecords)
    2337             :             {
    2338           0 :                 VSIFree(fitxa);
    2339           0 :                 return id;
    2340             :             }
    2341         498 :             i_dbf++;
    2342         498 :         } while (id_grafic == i);
    2343             :     }
    2344             : }  // End of MMCreateExtendedDBFIndex()
    2345             : 
    2346             : // READING/CREATING MIRAMON METADATA
    2347             : // Returns the value of an INI file. Used to read MiraMon metadata
    2348        6431 : CPL_DLL char *MMReturnValueFromSectionINIFile(const char *filename,
    2349             :                                               const char *section,
    2350             :                                               const char *key)
    2351             : {
    2352        6431 :     char *value = nullptr;
    2353             :     const char *pszLine;
    2354        6431 :     char *section_header = nullptr;
    2355        6431 :     size_t key_len = 0;
    2356             : 
    2357        6431 :     VSILFILE *file = VSIFOpenL(filename, "rb");
    2358        6431 :     if (file == nullptr)
    2359             :     {
    2360           0 :         CPLError(CE_Failure, CPLE_OpenFailed, "Cannot open INI file %s.",
    2361             :                  filename);
    2362           0 :         return nullptr;
    2363             :     }
    2364             : 
    2365        6431 :     if (key)
    2366        6147 :         key_len = strlen(key);
    2367             : 
    2368      454315 :     while ((pszLine = CPLReadLine2L(file, 10000, nullptr)) != nullptr)
    2369             :     {
    2370      450232 :         char *pszString = CPLRecode(pszLine, CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
    2371             : 
    2372             :         // Skip comments and empty lines
    2373      450232 :         if (*pszString == ';' || *pszString == '#' || *pszString == '\n' ||
    2374      450232 :             *pszString == '\r')
    2375             :         {
    2376           0 :             VSIFree(pszString);
    2377             :             // Move to next line
    2378           0 :             continue;
    2379             :         }
    2380             : 
    2381             :         // Check for section header
    2382      450232 :         if (*pszString == '[')
    2383             :         {
    2384       95380 :             char *section_end = strchr(pszString, ']');
    2385       95380 :             if (section_end != nullptr)
    2386             :             {
    2387       95380 :                 *section_end = '\0';  // Terminate the string at ']'
    2388       95380 :                 if (section_header)
    2389       88950 :                     VSIFree(section_header);
    2390       95380 :                 section_header = CPLStrdup(pszString + 1);  // Skip the '['
    2391             :             }
    2392       95380 :             VSIFree(pszString);
    2393       95380 :             continue;
    2394             :         }
    2395             : 
    2396      354852 :         if (key)
    2397             :         {
    2398             :             // If the current line belongs to the desired section
    2399      354569 :             if (section_header != nullptr &&
    2400      354569 :                 strcmp(section_header, section) == 0)
    2401             :             {
    2402             :                 // Check if the line contains the desired key
    2403       12884 :                 if (strncmp(pszString, key, key_len) == 0 &&
    2404        2487 :                     pszString[key_len] == '=')
    2405             :                 {
    2406             :                     // Extract the value
    2407        2065 :                     char *value_start = pszString + key_len + 1;
    2408        2065 :                     char *value_end = strstr(value_start, "\r\n");
    2409        2065 :                     if (value_end != nullptr)
    2410             :                     {
    2411           0 :                         *value_end =
    2412             :                             '\0';  // Terminate the string at newline character if found
    2413             :                     }
    2414             :                     else
    2415             :                     {
    2416        2065 :                         value_end = strstr(value_start, "\n");
    2417        2065 :                         if (value_end != nullptr)
    2418             :                         {
    2419           0 :                             *value_end =
    2420             :                                 '\0';  // Terminate the string at newline character if found
    2421             :                         }
    2422             :                         else
    2423             :                         {
    2424        2065 :                             value_end = strstr(value_start, "\r");
    2425        2065 :                             if (value_end != nullptr)
    2426             :                             {
    2427           0 :                                 *value_end =
    2428             :                                     '\0';  // Terminate the string at newline character if found
    2429             :                             }
    2430             :                         }
    2431             :                     }
    2432             : 
    2433        2065 :                     VSIFree(value);
    2434        2065 :                     value = CPLStrdup(value_start);
    2435        2065 :                     VSIFCloseL(file);
    2436        2065 :                     VSIFree(section_header);  // Free allocated memory
    2437        2065 :                     VSIFree(pszString);
    2438        2065 :                     return value;
    2439             :                 }
    2440             :             }
    2441             :         }
    2442             :         else
    2443             :         {
    2444         283 :             VSIFree(value);
    2445         283 :             value = nullptr;
    2446         283 :             if (section_header)
    2447             :             {
    2448         283 :                 if (!strcmp(section_header, section))
    2449             :                 {
    2450         283 :                     value = section_header;  // Freed out
    2451         283 :                     section_header = nullptr;
    2452             :                 }
    2453             :             }
    2454             : 
    2455         283 :             VSIFCloseL(file);
    2456         283 :             VSIFree(pszString);
    2457         283 :             VSIFree(section_header);
    2458         283 :             return value;
    2459             :         }
    2460      352504 :         VSIFree(pszString);
    2461             :     }
    2462             : 
    2463        4083 :     if (section_header)
    2464        4082 :         VSIFree(section_header);  // Free allocated memory
    2465        4083 :     VSIFCloseL(file);
    2466        4083 :     return value;
    2467             : }
    2468             : 
    2469             : // Retrieves EPSG codes from a CSV file based on provided geodetic identifiers.
    2470         273 : CPL_DLL int MMReturnCodeFromMM_m_idofic(const char *pMMSRS_or_pSRS,
    2471             :                                         char *szResult, MM_BYTE direction)
    2472             : {
    2473         273 :     char *aMMIDDBFFile = nullptr;  //m_idofic.dbf
    2474         273 :     VSILFILE *pfMMSRS = nullptr;
    2475             :     const char *pszLine;
    2476             :     size_t nLong;
    2477             :     char *id_geodes, *psidgeodes, *epsg;
    2478             : 
    2479         273 :     if (!pMMSRS_or_pSRS)
    2480             :     {
    2481          71 :         return 1;
    2482             :     }
    2483             : 
    2484             :     {
    2485             : #ifdef USE_ONLY_EMBEDDED_RESOURCE_FILES
    2486             :         const char *pszFilename = nullptr;
    2487             : #else
    2488         202 :         const char *pszFilename = CPLFindFile("gdal", "MM_m_idofic.csv");
    2489             : #endif
    2490             : #ifdef EMBED_RESOURCE_FILES
    2491             :         if (!pszFilename || EQUAL(pszFilename, "MM_m_idofic.csv"))
    2492             :         {
    2493             :             pfMMSRS = VSIFileFromMemBuffer(
    2494             :                 nullptr, (GByte *)(MiraMonGetMM_m_idofic_csv()),
    2495             :                 (int)(strlen(MiraMonGetMM_m_idofic_csv())),
    2496             :                 /* bTakeOwnership = */ false);
    2497             :         }
    2498             :         else
    2499             : #endif
    2500         202 :             if (pszFilename)
    2501             :         {
    2502         202 :             aMMIDDBFFile = CPLStrdup(pszFilename);
    2503             :         }
    2504             :     }
    2505             : 
    2506             : #ifdef EMBED_RESOURCE_FILES
    2507             :     if (!pfMMSRS)
    2508             : #endif
    2509             :     {
    2510         202 :         if (!aMMIDDBFFile)
    2511             :         {
    2512           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    2513             :                      "Error opening data\\MM_m_idofic.csv.\n");
    2514           0 :             return 1;
    2515             :         }
    2516             : 
    2517             :         // Opening the file with SRS information
    2518         202 :         if (nullptr == (pfMMSRS = VSIFOpenL(aMMIDDBFFile, "r")))
    2519             :         {
    2520           0 :             VSIFree(aMMIDDBFFile);
    2521           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    2522             :                      "Error opening data\\MM_m_idofic.csv.\n");
    2523           0 :             return 1;
    2524             :         }
    2525         202 :         VSIFree(aMMIDDBFFile);
    2526             :     }
    2527             : 
    2528             :     // Checking the header of the csv file
    2529         202 :     pszLine = CPLReadLine2L(pfMMSRS, 10000, nullptr);
    2530             : 
    2531         202 :     if (!pszLine)
    2532             : 
    2533             :     {
    2534           0 :         VSIFCloseL(pfMMSRS);
    2535           0 :         CPLError(CE_Failure, CPLE_NotSupported,
    2536             :                  "Wrong format in data\\MM_m_idofic.csv.\n");
    2537           0 :         return 1;
    2538             :     }
    2539         202 :     id_geodes = MM_stristr(pszLine, "ID_GEODES");
    2540         202 :     if (!id_geodes)
    2541             :     {
    2542           0 :         VSIFCloseL(pfMMSRS);
    2543           0 :         CPLError(CE_Failure, CPLE_NotSupported,
    2544             :                  "Wrong format in data\\MM_m_idofic.csv.\n");
    2545           0 :         return 1;
    2546             :     }
    2547         202 :     id_geodes[strlen("ID_GEODES")] = '\0';
    2548         202 :     psidgeodes = MM_stristr(pszLine, "PSIDGEODES");
    2549         202 :     if (!psidgeodes)
    2550             :     {
    2551           0 :         VSIFCloseL(pfMMSRS);
    2552           0 :         CPLError(CE_Failure, CPLE_NotSupported,
    2553             :                  "Wrong format in data\\MM_m_idofic.csv.\n");
    2554           0 :         return 1;
    2555             :     }
    2556         202 :     psidgeodes[strlen("PSIDGEODES")] = '\0';
    2557             : 
    2558             :     // Is PSIDGEODES in first place?
    2559         202 :     if (strncmp(pszLine, psidgeodes, strlen("PSIDGEODES")))
    2560             :     {
    2561           0 :         VSIFCloseL(pfMMSRS);
    2562           0 :         CPLError(CE_Failure, CPLE_NotSupported,
    2563             :                  "Wrong format in data\\MM_m_idofic.csv.\n");
    2564           0 :         return 1;
    2565             :     }
    2566             :     // Is ID_GEODES after PSIDGEODES?
    2567         202 :     if (strncmp(pszLine + strlen("PSIDGEODES") + 1, "ID_GEODES",
    2568             :                 strlen("ID_GEODES")))
    2569             :     {
    2570           0 :         VSIFCloseL(pfMMSRS);
    2571           0 :         CPLError(CE_Failure, CPLE_NotSupported,
    2572             :                  "Wrong format in data\\MM_m_idofic.csv.\n");
    2573           0 :         return 1;
    2574             :     }
    2575             : 
    2576             :     // Looking for the information.
    2577       49745 :     while ((pszLine = CPLReadLine2L(pfMMSRS, 10000, nullptr)) != nullptr)
    2578             :     {
    2579       49683 :         id_geodes = strstr(pszLine, ";");
    2580       49683 :         if (!id_geodes)
    2581             :         {
    2582           0 :             VSIFCloseL(pfMMSRS);
    2583           0 :             CPLError(CE_Failure, CPLE_NotSupported,
    2584             :                      "Wrong format in data\\MM_m_idofic.csv.\n");
    2585           0 :             return 1;
    2586             :         }
    2587             : 
    2588       49683 :         psidgeodes = strstr(id_geodes + 1, ";");
    2589       49683 :         if (!psidgeodes)
    2590             :         {
    2591           0 :             VSIFCloseL(pfMMSRS);
    2592           0 :             CPLError(CE_Failure, CPLE_NotSupported,
    2593             :                      "Wrong format in data\\MM_m_idofic.csv.\n");
    2594           0 :             return 1;
    2595             :         }
    2596             : 
    2597       49683 :         id_geodes[(ptrdiff_t)psidgeodes - (ptrdiff_t)id_geodes] = '\0';
    2598       49683 :         psidgeodes = CPLStrdup(pszLine);
    2599       49683 :         psidgeodes[(ptrdiff_t)id_geodes - (ptrdiff_t)pszLine] = '\0';
    2600       49683 :         id_geodes++;
    2601             : 
    2602       49683 :         if (direction == EPSG_FROM_MMSRS)
    2603             :         {
    2604             :             // I have pMMSRS and I want pSRS
    2605       45243 :             if (strcmp(pMMSRS_or_pSRS, id_geodes))
    2606             :             {
    2607       45124 :                 VSIFree(psidgeodes);
    2608       45124 :                 continue;
    2609             :             }
    2610             : 
    2611         119 :             epsg = strstr(psidgeodes, "EPSG:");
    2612         119 :             nLong = strlen("EPSG:");
    2613         119 :             if (epsg && !strncmp(epsg, psidgeodes, nLong))
    2614             :             {
    2615         119 :                 if (epsg[nLong] != '\0')
    2616             :                 {
    2617         119 :                     strcpy(szResult, epsg + nLong);
    2618         119 :                     VSIFree(psidgeodes);
    2619         119 :                     VSIFCloseL(pfMMSRS);
    2620         119 :                     return 0;  // found
    2621             :                 }
    2622             :                 else
    2623             :                 {
    2624           0 :                     VSIFCloseL(pfMMSRS);
    2625           0 :                     *szResult = '\0';
    2626           0 :                     VSIFree(psidgeodes);
    2627           0 :                     return 1;  // not found
    2628             :                 }
    2629             :             }
    2630             :         }
    2631             :         else
    2632             :         {
    2633             :             // I have pSRS and I want pMMSRS
    2634        4440 :             epsg = strstr(psidgeodes, "EPSG:");
    2635        4440 :             nLong = strlen("EPSG:");
    2636        4440 :             if (epsg && !strncmp(epsg, psidgeodes, nLong))
    2637             :             {
    2638        3483 :                 if (epsg[nLong] != '\0')
    2639             :                 {
    2640        3483 :                     if (!strcmp(pMMSRS_or_pSRS, epsg + nLong))
    2641             :                     {
    2642          21 :                         strcpy(szResult, id_geodes);
    2643          21 :                         VSIFCloseL(pfMMSRS);
    2644          21 :                         VSIFree(psidgeodes);
    2645          21 :                         return 0;  // found
    2646             :                     }
    2647             :                 }
    2648             :             }
    2649             :         }
    2650        4419 :         VSIFree(psidgeodes);
    2651             :     }
    2652             : 
    2653          62 :     VSIFCloseL(pfMMSRS);
    2654          62 :     return 1;  // not found
    2655             : }
    2656             : 
    2657             : // Verifies the version of a MiraMon REL 4 file.
    2658         287 : CPL_DLL int MMCheck_REL_FILE(const char *szREL_file)
    2659             : {
    2660             :     char *pszLine;
    2661             :     VSILFILE *pF;
    2662             : 
    2663             :     // Does the REL file exist?
    2664         287 :     pF = VSIFOpenL(szREL_file, "r");
    2665         287 :     if (!pF)
    2666             :     {
    2667           3 :         CPLError(CE_Failure, CPLE_OpenFailed, "The file %s must exist.",
    2668             :                  szREL_file);
    2669           3 :         return 1;
    2670             :     }
    2671         284 :     VSIFCloseL(pF);
    2672             : 
    2673             :     // Does the REL file have VERSION?
    2674             :     pszLine =
    2675         284 :         MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO, nullptr);
    2676         284 :     if (!pszLine)
    2677             :     {
    2678           1 :         CPLError(CE_Failure, CPLE_OpenFailed,
    2679             :                  "The file \"%s\" must be REL4. "
    2680             :                  "You can use ConvREL.exe from MiraMon software "
    2681             :                  " or GeM+ "
    2682             :                  "to convert this file to REL4.",
    2683             :                  szREL_file);
    2684           1 :         return 1;
    2685             :     }
    2686         283 :     VSIFree(pszLine);
    2687             : 
    2688             :     // Does the REL file have the correct VERSION?
    2689             :     // Vers>=4?
    2690             :     pszLine =
    2691         283 :         MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO, KEY_Vers);
    2692         283 :     if (pszLine)
    2693             :     {
    2694         283 :         if (*pszLine == '\0' || atoi(pszLine) < (int)MM_VERS)
    2695             :         {
    2696           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    2697             :                      "The file \"%s\" must have %s>=%d.", szREL_file, KEY_Vers,
    2698             :                      MM_VERS);
    2699           0 :             VSIFree(pszLine);
    2700           0 :             return 1;
    2701             :         }
    2702         283 :         VSIFree(pszLine);
    2703             :     }
    2704             :     else
    2705             :     {
    2706           0 :         CPLError(CE_Failure, CPLE_OpenFailed,
    2707             :                  "The file \"%s\" must have %s>=%d.", szREL_file, KEY_Vers,
    2708             :                  MM_VERS);
    2709           0 :         return 1;
    2710             :     }
    2711             : 
    2712             :     // SubVers>=0?
    2713         283 :     pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO,
    2714             :                                               KEY_SubVers);
    2715         283 :     if (pszLine)
    2716             :     {
    2717         283 :         if (*pszLine == '\0' || atoi(pszLine) < (int)MM_SUBVERS_ACCEPTED)
    2718             :         {
    2719           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    2720             :                      "The file \"%s\" must have %s>=%d.", szREL_file,
    2721             :                      KEY_SubVers, MM_SUBVERS_ACCEPTED);
    2722             : 
    2723           0 :             VSIFree(pszLine);
    2724           0 :             return 1;
    2725             :         }
    2726         283 :         VSIFree(pszLine);
    2727             :     }
    2728             :     else
    2729             :     {
    2730           0 :         CPLError(CE_Failure, CPLE_OpenFailed,
    2731             :                  "The file \"%s\" must have %s>=%d.", szREL_file, KEY_SubVers,
    2732             :                  MM_SUBVERS_ACCEPTED);
    2733           0 :         return 1;
    2734             :     }
    2735             : 
    2736             :     // VersMetaDades>=4?
    2737         283 :     pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO,
    2738             :                                               KEY_VersMetaDades);
    2739         283 :     if (pszLine)
    2740             :     {
    2741         282 :         if (*pszLine == '\0' || atoi(pszLine) < (int)MM_VERS_METADADES_ACCEPTED)
    2742             :         {
    2743           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    2744             :                      "The file \"%s\" must have %s>=%d.", szREL_file,
    2745             :                      KEY_VersMetaDades, MM_VERS_METADADES_ACCEPTED);
    2746           0 :             VSIFree(pszLine);
    2747           0 :             return 1;
    2748             :         }
    2749         282 :         VSIFree(pszLine);
    2750             :     }
    2751             :     else
    2752             :     {
    2753           1 :         CPLError(CE_Failure, CPLE_OpenFailed,
    2754             :                  "The file \"%s\" must have %s>=%d.", szREL_file,
    2755             :                  KEY_VersMetaDades, MM_VERS_METADADES_ACCEPTED);
    2756           1 :         return 1;
    2757             :     }
    2758             : 
    2759             :     // SubVersMetaDades>=0?
    2760         282 :     pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO,
    2761             :                                               KEY_SubVersMetaDades);
    2762         282 :     if (pszLine)
    2763             :     {
    2764         282 :         if (*pszLine == '\0' || atoi(pszLine) < (int)MM_SUBVERS_METADADES)
    2765             :         {
    2766           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    2767             :                      "The file \"%s\" must have %s>=%d.", szREL_file,
    2768             :                      KEY_SubVersMetaDades, MM_SUBVERS_METADADES);
    2769           0 :             VSIFree(pszLine);
    2770           0 :             return 1;
    2771             :         }
    2772         282 :         VSIFree(pszLine);
    2773             :     }
    2774             :     else
    2775             :     {
    2776           0 :         CPLError(CE_Failure, CPLE_OpenFailed,
    2777             :                  "The file \"%s\" must have %s>=%d.", szREL_file,
    2778             :                  KEY_SubVersMetaDades, MM_SUBVERS_METADADES);
    2779           0 :         return 1;
    2780             :     }
    2781         282 :     return 0;
    2782             : }
    2783             : 
    2784             : // Generates an identifier that REL 4 MiraMon metadata needs.
    2785         177 : CPL_DLL void MMGenerateFileIdentifierFromMetadataFileName(char *pMMFN,
    2786             :                                                           char *aFileIdentifier)
    2787             : {
    2788             :     char aCharRand[8];
    2789             :     static const char aCharset[] =
    2790             :         "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    2791             :     int i, len_charset;
    2792             : 
    2793         177 :     memset(aFileIdentifier, '\0', MM_MAX_LEN_LAYER_IDENTIFIER);
    2794             : 
    2795         177 :     aCharRand[0] = '_';
    2796         177 :     len_charset = (int)strlen(aCharset);
    2797        1239 :     for (i = 1; i < 7; i++)
    2798             :     {
    2799             : #ifndef __COVERITY__
    2800        1062 :         aCharRand[i] = aCharset[rand() % (len_charset - 1)];
    2801             : #else
    2802             :         aCharRand[i] = aCharset[i % (len_charset - 1)];
    2803             : #endif
    2804             :     }
    2805         177 :     aCharRand[7] = '\0';
    2806         177 :     CPLStrlcpy(aFileIdentifier, pMMFN, MM_MAX_LEN_LAYER_IDENTIFIER - 7);
    2807         177 :     strcat(aFileIdentifier, aCharRand);
    2808         177 :     return;
    2809             : }
    2810             : 
    2811             : /* -------------------------------------------------------------------- */
    2812             : /*      Managing errors and warnings                                    */
    2813             : /* -------------------------------------------------------------------- */
    2814             : 
    2815             : // Checks for potential arithmetic overflow when performing multiplication
    2816             : // operations between two GUInt64 values and converting the result to size_t.
    2817             : // Important for 32 vs. 64 bit compiling compatibility.
    2818        5479 : CPL_DLL int MMCheckSize_t(GUInt64 nCount, GUInt64 nSize)
    2819             : {
    2820             :     if ((size_t)nCount != nCount)
    2821             :         return 1;
    2822             : 
    2823             :     if ((size_t)nSize != nSize)
    2824             :         return 1;
    2825             : 
    2826             : #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
    2827        5479 :     if (nCount != 0 && nSize > SIZE_MAX / nCount)
    2828             : #else
    2829             :     if (nCount != 0 && nSize > (1000 * 1000 * 1000U) / nCount)
    2830             : #endif
    2831             :     {
    2832           0 :         CPLError(CE_Failure, CPLE_OutOfMemory, "Overflow in MMCheckSize_t()");
    2833           0 :         return 1;
    2834             :     }
    2835        5479 :     return 0;
    2836             : }
    2837             : 
    2838             : CPL_C_END  // Necessary for compiling in GDAL project

Generated by: LCOV version 1.14