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

Generated by: LCOV version 1.14