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