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 : #include "mm_wrlayr.h" // For VSIFCloseL()...
21 : #ifdef EMBED_RESOURCE_FILES
22 : #include "embedded_resources.h"
23 : #endif
24 :
25 : CPL_C_START // Necessary for compiling in GDAL project
26 : #include "cpl_string.h" // For CPL_ENC_UTF8
27 :
28 : char szInternalGraphicIdentifierEng[MM_MAX_IDENTIFIER_SIZE];
29 : char szInternalGraphicIdentifierCat[MM_MAX_IDENTIFIER_SIZE];
30 : char szInternalGraphicIdentifierSpa[MM_MAX_IDENTIFIER_SIZE];
31 :
32 : char szNumberOfVerticesEng[MM_MAX_IDENTIFIER_SIZE];
33 : char szNumberOfVerticesCat[MM_MAX_IDENTIFIER_SIZE];
34 : char szNumberOfVerticesSpa[MM_MAX_IDENTIFIER_SIZE];
35 :
36 : char szLengthOfAarcEng[MM_MAX_IDENTIFIER_SIZE];
37 : char szLengthOfAarcCat[MM_MAX_IDENTIFIER_SIZE];
38 : char szLengthOfAarcSpa[MM_MAX_IDENTIFIER_SIZE];
39 :
40 : char szInitialNodeEng[MM_MAX_IDENTIFIER_SIZE];
41 : char szInitialNodeCat[MM_MAX_IDENTIFIER_SIZE];
42 : char szInitialNodeSpa[MM_MAX_IDENTIFIER_SIZE];
43 :
44 : char szFinalNodeEng[MM_MAX_IDENTIFIER_SIZE];
45 : char szFinalNodeCat[MM_MAX_IDENTIFIER_SIZE];
46 : char szFinalNodeSpa[MM_MAX_IDENTIFIER_SIZE];
47 :
48 : char szNumberOfArcsToNodeEng[MM_MAX_IDENTIFIER_SIZE];
49 : char szNumberOfArcsToNodeCat[MM_MAX_IDENTIFIER_SIZE];
50 : char szNumberOfArcsToNodeSpa[MM_MAX_IDENTIFIER_SIZE];
51 :
52 : char szNodeTypeEng[MM_MAX_IDENTIFIER_SIZE];
53 : char szNodeTypeCat[MM_MAX_IDENTIFIER_SIZE];
54 : char szNodeTypeSpa[MM_MAX_IDENTIFIER_SIZE];
55 :
56 : char szPerimeterOfThePolygonEng[MM_MAX_IDENTIFIER_SIZE];
57 : char szPerimeterOfThePolygonCat[MM_MAX_IDENTIFIER_SIZE];
58 : char szPerimeterOfThePolygonSpa[MM_MAX_IDENTIFIER_SIZE];
59 :
60 : char szAreaOfThePolygonEng[MM_MAX_IDENTIFIER_SIZE];
61 : char szAreaOfThePolygonCat[MM_MAX_IDENTIFIER_SIZE];
62 : char szAreaOfThePolygonSpa[MM_MAX_IDENTIFIER_SIZE];
63 :
64 : char szNumberOfArcsEng[MM_MAX_IDENTIFIER_SIZE];
65 : char szNumberOfArcsCat[MM_MAX_IDENTIFIER_SIZE];
66 : char szNumberOfArcsSpa[MM_MAX_IDENTIFIER_SIZE];
67 :
68 : char szNumberOfElementaryPolygonsEng[MM_MAX_IDENTIFIER_SIZE];
69 : char szNumberOfElementaryPolygonsCat[MM_MAX_IDENTIFIER_SIZE];
70 : char szNumberOfElementaryPolygonsSpa[MM_MAX_IDENTIFIER_SIZE];
71 :
72 328 : void MM_FillFieldDescriptorByLanguage(void)
73 : {
74 328 : CPLStrlcpy(szInternalGraphicIdentifierEng, "Internal Graphic identifier",
75 : MM_MAX_IDENTIFIER_SIZE);
76 328 : CPLStrlcpy(szInternalGraphicIdentifierCat, "Identificador Grafic intern",
77 : MM_MAX_IDENTIFIER_SIZE);
78 328 : *(unsigned char *)&szInternalGraphicIdentifierCat[16] = MM_a_WITH_GRAVE;
79 328 : CPLStrlcpy(szInternalGraphicIdentifierSpa, "Identificador Grafico interno",
80 : MM_MAX_IDENTIFIER_SIZE);
81 328 : *(unsigned char *)&szInternalGraphicIdentifierSpa[16] = MM_a_WITH_ACUTE;
82 :
83 328 : CPLStrlcpy(szNumberOfVerticesEng, "Number of vertices",
84 : MM_MAX_IDENTIFIER_SIZE);
85 328 : CPLStrlcpy(szNumberOfVerticesCat, "Nombre de vertexs",
86 : MM_MAX_IDENTIFIER_SIZE);
87 328 : CPLStrlcpy(szNumberOfVerticesSpa, "Numero de vertices",
88 : MM_MAX_IDENTIFIER_SIZE);
89 328 : *(unsigned char *)&szNumberOfVerticesCat[11] = MM_e_WITH_GRAVE;
90 328 : *(unsigned char *)&szNumberOfVerticesSpa[1] = MM_u_WITH_ACUTE;
91 328 : *(unsigned char *)&szNumberOfVerticesSpa[11] = MM_e_WITH_ACUTE;
92 :
93 328 : CPLStrlcpy(szLengthOfAarcEng, "Length of arc", MM_MAX_IDENTIFIER_SIZE);
94 328 : CPLStrlcpy(szLengthOfAarcCat, "Longitud de l'arc", MM_MAX_IDENTIFIER_SIZE);
95 328 : CPLStrlcpy(szLengthOfAarcSpa, "Longitud del arco", MM_MAX_IDENTIFIER_SIZE);
96 :
97 328 : CPLStrlcpy(szInitialNodeEng, "Initial node", MM_MAX_IDENTIFIER_SIZE);
98 328 : CPLStrlcpy(szInitialNodeCat, "Node inicial", MM_MAX_IDENTIFIER_SIZE);
99 328 : CPLStrlcpy(szInitialNodeSpa, "Nodo inicial", MM_MAX_IDENTIFIER_SIZE);
100 :
101 328 : CPLStrlcpy(szFinalNodeEng, "Final node", MM_MAX_IDENTIFIER_SIZE);
102 328 : CPLStrlcpy(szFinalNodeCat, "Node final", MM_MAX_IDENTIFIER_SIZE);
103 328 : CPLStrlcpy(szFinalNodeSpa, "Nodo final", MM_MAX_IDENTIFIER_SIZE);
104 :
105 328 : CPLStrlcpy(szNumberOfArcsToNodeEng, "Number of arcs to node",
106 : MM_MAX_IDENTIFIER_SIZE);
107 328 : CPLStrlcpy(szNumberOfArcsToNodeCat, "Nombre d'arcs al node",
108 : MM_MAX_IDENTIFIER_SIZE);
109 328 : CPLStrlcpy(szNumberOfArcsToNodeSpa, "Numero de arcos al nodo",
110 : MM_MAX_IDENTIFIER_SIZE);
111 328 : *(unsigned char *)&szNumberOfArcsToNodeSpa[1] = MM_u_WITH_ACUTE;
112 :
113 328 : CPLStrlcpy(szNodeTypeEng, "Node type", MM_MAX_IDENTIFIER_SIZE);
114 328 : CPLStrlcpy(szNodeTypeCat, "Tipus de node", MM_MAX_IDENTIFIER_SIZE);
115 328 : CPLStrlcpy(szNodeTypeSpa, "Tipo de nodo", MM_MAX_IDENTIFIER_SIZE);
116 :
117 328 : CPLStrlcpy(szPerimeterOfThePolygonEng, "Perimeter of the polygon",
118 : MM_MAX_IDENTIFIER_SIZE);
119 328 : CPLStrlcpy(szPerimeterOfThePolygonCat, "Perimetre del poligon",
120 : MM_MAX_IDENTIFIER_SIZE);
121 328 : CPLStrlcpy(szPerimeterOfThePolygonSpa, "Perimetro del poligono",
122 : MM_MAX_IDENTIFIER_SIZE);
123 :
124 328 : *(unsigned char *)&szPerimeterOfThePolygonCat[3] = MM_i_WITH_ACUTE;
125 328 : *(unsigned char *)&szPerimeterOfThePolygonSpa[3] = MM_i_WITH_ACUTE;
126 328 : *(unsigned char *)&szPerimeterOfThePolygonCat[17] = MM_i_WITH_ACUTE;
127 328 : *(unsigned char *)&szPerimeterOfThePolygonSpa[17] = MM_i_WITH_ACUTE;
128 :
129 328 : CPLStrlcpy(szAreaOfThePolygonEng, "Area of the polygon",
130 : MM_MAX_IDENTIFIER_SIZE);
131 328 : CPLStrlcpy(szAreaOfThePolygonCat, "Area del poligon",
132 : MM_MAX_IDENTIFIER_SIZE);
133 328 : CPLStrlcpy(szAreaOfThePolygonSpa, "Area del poligono",
134 : MM_MAX_IDENTIFIER_SIZE);
135 :
136 328 : *(unsigned char *)&szAreaOfThePolygonCat[0] = MM_A_WITH_GRAVE;
137 328 : *(unsigned char *)&szAreaOfThePolygonSpa[0] = MM_A_WITH_ACUTE;
138 328 : *(unsigned char *)&szAreaOfThePolygonCat[12] = MM_i_WITH_ACUTE;
139 328 : *(unsigned char *)&szAreaOfThePolygonSpa[12] = MM_i_WITH_ACUTE;
140 :
141 328 : CPLStrlcpy(szNumberOfArcsEng, "Number of arcs", MM_MAX_IDENTIFIER_SIZE);
142 328 : CPLStrlcpy(szNumberOfArcsCat, "Nombre d'arcs", MM_MAX_IDENTIFIER_SIZE);
143 328 : CPLStrlcpy(szNumberOfArcsSpa, "Numero de arcos", MM_MAX_IDENTIFIER_SIZE);
144 :
145 328 : *(unsigned char *)&szNumberOfArcsSpa[1] = MM_u_WITH_ACUTE;
146 :
147 328 : CPLStrlcpy(szNumberOfElementaryPolygonsEng, "Number of elementary polygons",
148 : MM_MAX_IDENTIFIER_SIZE);
149 328 : CPLStrlcpy(szNumberOfElementaryPolygonsCat, "Nombre de poligons elementals",
150 : MM_MAX_IDENTIFIER_SIZE);
151 328 : CPLStrlcpy(szNumberOfElementaryPolygonsSpa,
152 : "Numero de poligonos elementales", MM_MAX_IDENTIFIER_SIZE);
153 :
154 328 : *(unsigned char *)&szNumberOfElementaryPolygonsSpa[1] = MM_u_WITH_ACUTE;
155 328 : *(unsigned char *)&szNumberOfElementaryPolygonsCat[13] = MM_i_WITH_ACUTE;
156 328 : *(unsigned char *)&szNumberOfElementaryPolygonsSpa[13] = MM_i_WITH_ACUTE;
157 328 : }
158 :
159 : const char *MM_pszLogFilename = nullptr;
160 :
161 : static const char MM_EmptyString[] = {""};
162 : #define MM_SetEndOfString (*MM_EmptyString)
163 :
164 1516 : void fclose_and_nullify(VSILFILE **pFunc)
165 : {
166 1516 : if (!pFunc || !(*pFunc))
167 355 : return;
168 1161 : VSIFCloseL(*pFunc);
169 1161 : *pFunc = nullptr;
170 : }
171 :
172 : // CREATING AN EXTENDED MIRAMON DBF
173 4108 : void MM_InitializeField(struct MM_FIELD *pField)
174 : {
175 4108 : memset(pField, '\0', sizeof(*pField));
176 4108 : pField->FieldType = 'C';
177 4108 : pField->GeoTopoTypeField = MM_NO_ES_CAMP_GEOTOPO;
178 4108 : }
179 :
180 : #define MM_ACCEPTABLE_NUMBER_OF_FIELDS 20000
181 :
182 306 : struct MM_FIELD *MM_CreateAllFields(MM_EXT_DBF_N_FIELDS nFields)
183 : {
184 : struct MM_FIELD *camp;
185 : MM_EXT_DBF_N_FIELDS i;
186 :
187 : // MiraMon could accept a number of fields 13.4 million
188 : // but GDAL prefers to limit that to 20.000 to avoid
189 : // too large memory allocation attempts with corrupted datasets
190 306 : if (nFields > MM_ACCEPTABLE_NUMBER_OF_FIELDS)
191 : {
192 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
193 : "More than 20000 fields not accepted");
194 0 : return nullptr;
195 : }
196 :
197 : #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
198 306 : if (nFields >= UINT32_MAX / sizeof(*camp))
199 0 : return nullptr;
200 : #else
201 : if (nFields >= (1000U * 1000 * 1000) / sizeof(*camp))
202 : return nullptr;
203 : #endif
204 :
205 306 : if ((camp = VSICalloc(nFields, sizeof(*camp))) == nullptr)
206 0 : return nullptr;
207 :
208 2613 : for (i = 0; i < nFields; i++)
209 2307 : MM_InitializeField(camp + i);
210 306 : return camp;
211 : }
212 :
213 191 : static struct MM_DATA_BASE_XP *MM_CreateEmptyHeader(MM_EXT_DBF_N_FIELDS nFields)
214 : {
215 : struct MM_DATA_BASE_XP *data_base_XP;
216 :
217 191 : if ((data_base_XP = (struct MM_DATA_BASE_XP *)VSICalloc(
218 : 1, sizeof(struct MM_DATA_BASE_XP))) == nullptr)
219 0 : return nullptr;
220 :
221 191 : if (nFields == 0)
222 : {
223 : ;
224 : }
225 : else
226 : {
227 191 : data_base_XP->pField = (struct MM_FIELD *)MM_CreateAllFields(nFields);
228 191 : if (!data_base_XP->pField)
229 : {
230 0 : VSIFree(data_base_XP);
231 0 : return nullptr;
232 : }
233 : }
234 191 : data_base_XP->nFields = nFields;
235 191 : return data_base_XP;
236 : }
237 :
238 191 : struct MM_DATA_BASE_XP *MM_CreateDBFHeader(MM_EXT_DBF_N_FIELDS n_camps,
239 : MM_BYTE charset)
240 : {
241 : struct MM_DATA_BASE_XP *bd_xp;
242 : struct MM_FIELD *camp;
243 : MM_EXT_DBF_N_FIELDS i;
244 :
245 191 : if (nullptr == (bd_xp = MM_CreateEmptyHeader(n_camps)))
246 0 : return nullptr;
247 :
248 191 : bd_xp->CharSet = charset;
249 :
250 191 : strcpy(bd_xp->ReadingMode, "a+b");
251 :
252 191 : bd_xp->IdGraficField = n_camps;
253 191 : bd_xp->IdEntityField = MM_MAX_EXT_DBF_N_FIELDS_TYPE;
254 191 : bd_xp->dbf_version = (MM_BYTE)((n_camps > MM_MAX_N_CAMPS_DBF_CLASSICA)
255 : ? MM_MARCA_VERSIO_1_DBF_ESTESA
256 : : MM_MARCA_DBASE4);
257 :
258 1417 : for (i = 0, camp = bd_xp->pField; i < n_camps; i++, camp++)
259 : {
260 1226 : MM_InitializeField(camp);
261 1226 : if (i < 99999)
262 1226 : snprintf(camp->FieldName, sizeof(camp->FieldName), "CAMP%05u",
263 1226 : (unsigned)(i + 1));
264 : else
265 0 : snprintf(camp->FieldName, sizeof(camp->FieldName), "CM%u",
266 0 : (unsigned)(i + 1));
267 1226 : camp->FieldType = 'C';
268 1226 : camp->DecimalsIfFloat = 0;
269 1226 : camp->BytesPerField = 50;
270 : }
271 191 : return bd_xp;
272 : }
273 :
274 1226 : static MM_BYTE MM_GetDefaultDesiredDBFFieldWidth(const struct MM_FIELD *camp)
275 : {
276 : size_t a, b, c, d, e;
277 :
278 1226 : b = strlen(camp->FieldName);
279 1226 : c = strlen(camp->FieldDescription[0]);
280 :
281 1226 : if (camp->FieldType == 'D')
282 : {
283 68 : d = (b > c ? b : c);
284 68 : a = (size_t)camp->BytesPerField + 2;
285 68 : return (MM_BYTE)(a > d ? a : d);
286 : }
287 1158 : a = camp->BytesPerField;
288 1158 : d = (unsigned int)(b > c ? b : c);
289 1158 : e = (a > d ? a : d);
290 1158 : return (MM_BYTE)(e < 80 ? e : 80);
291 : }
292 :
293 9063 : static MM_BOOLEAN MM_is_field_name_lowercase(const char *szChain)
294 : {
295 : const char *p;
296 :
297 56071 : for (p = szChain; *p; p++)
298 : {
299 50335 : if ((*p >= 'a' && *p <= 'z'))
300 3327 : return TRUE;
301 : }
302 5736 : return FALSE;
303 : }
304 :
305 : static MM_BOOLEAN
306 9095 : MM_Is_classical_DBF_field_name_or_lowercase(const char *szChain)
307 : {
308 : const char *p;
309 :
310 76551 : for (p = szChain; *p; p++)
311 : {
312 67488 : if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
313 6275 : (*p >= '0' && *p <= '9') || *p == '_')
314 : ;
315 : else
316 32 : return FALSE;
317 : }
318 9063 : if (szChain[0] == '_')
319 0 : return FALSE;
320 9063 : return TRUE;
321 : }
322 :
323 : static MM_BOOLEAN
324 81431 : MM_Is_character_valid_for_extended_DBF_field_name(int valor,
325 : int *valor_substitut)
326 : {
327 81431 : if (valor_substitut)
328 : {
329 0 : switch (valor)
330 : {
331 0 : case 32:
332 0 : *valor_substitut = '_';
333 0 : return FALSE;
334 0 : case 91:
335 0 : *valor_substitut = '(';
336 0 : return FALSE;
337 0 : case 93:
338 0 : *valor_substitut = ')';
339 0 : return FALSE;
340 0 : case 96:
341 0 : *valor_substitut = '\'';
342 0 : return FALSE;
343 0 : case 127:
344 0 : *valor_substitut = '_';
345 0 : return FALSE;
346 0 : case 168:
347 0 : *valor_substitut = '-';
348 0 : return FALSE;
349 : }
350 : }
351 : else
352 : {
353 81431 : if (valor < 32 || valor == 91 || valor == 93 || valor == 96 ||
354 81431 : valor == 127 || valor == 168)
355 0 : return FALSE;
356 : }
357 81431 : return TRUE;
358 : }
359 :
360 10213 : static int MM_ISExtendedNameBD_XP(const char *nom_camp)
361 : {
362 : size_t mida, j;
363 :
364 10213 : mida = strlen(nom_camp);
365 10213 : if (mida >= MM_MAX_LON_FIELD_NAME_DBF)
366 0 : return MM_DBF_NAME_NO_VALID;
367 :
368 91644 : for (j = 0; j < mida; j++)
369 : {
370 81431 : if (!MM_Is_character_valid_for_extended_DBF_field_name(
371 81431 : (unsigned char)nom_camp[j], nullptr))
372 0 : return MM_DBF_NAME_NO_VALID;
373 : }
374 :
375 10213 : if (mida >= MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF)
376 1118 : return MM_VALID_EXTENDED_DBF_NAME;
377 :
378 9095 : if (!MM_Is_classical_DBF_field_name_or_lowercase(nom_camp))
379 32 : return MM_VALID_EXTENDED_DBF_NAME;
380 :
381 9063 : if (MM_is_field_name_lowercase(nom_camp))
382 3327 : return MM_DBF_NAME_LOWERCASE_AND_VALID;
383 :
384 5736 : return NM_CLASSICAL_DBF_AND_VALID_NAME;
385 : }
386 :
387 530 : static MM_BYTE MM_CalculateBytesExtendedFieldName(struct MM_FIELD *camp)
388 : {
389 530 : camp->reserved_2[MM_OFFSET_RESERVED2_EXTENDED_NAME_SIZE] =
390 530 : (MM_BYTE)strlen(camp->FieldName);
391 530 : return MM_DonaBytesNomEstesCamp(camp);
392 : }
393 :
394 : static MM_ACCUMULATED_BYTES_TYPE_DBF
395 191 : MM_CalculateBytesExtendedFieldNames(const struct MM_DATA_BASE_XP *bd_xp)
396 : {
397 191 : MM_ACCUMULATED_BYTES_TYPE_DBF bytes_acumulats = 0;
398 : MM_EXT_DBF_N_FIELDS i_camp;
399 :
400 1417 : for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
401 : {
402 1226 : if (MM_VALID_EXTENDED_DBF_NAME ==
403 1226 : MM_ISExtendedNameBD_XP(bd_xp->pField[i_camp].FieldName))
404 91 : bytes_acumulats +=
405 91 : MM_CalculateBytesExtendedFieldName(bd_xp->pField + i_camp);
406 : }
407 :
408 191 : return bytes_acumulats;
409 : }
410 :
411 : static MM_FIRST_RECORD_OFFSET_TYPE
412 191 : MM_CalculateBytesFirstRecordOffset(struct MM_DATA_BASE_XP *bd_xp)
413 : {
414 191 : if (bd_xp)
415 191 : return (32 + 32 * bd_xp->nFields + 1 +
416 191 : MM_CalculateBytesExtendedFieldNames(bd_xp));
417 0 : return 0;
418 : }
419 :
420 191 : static void MM_CheckDBFHeader(struct MM_DATA_BASE_XP *bd_xp)
421 : {
422 : struct MM_FIELD *camp;
423 : MM_EXT_DBF_N_FIELDS i;
424 191 : MM_BOOLEAN cal_DBF_estesa = FALSE;
425 :
426 191 : bd_xp->BytesPerRecord = 1;
427 1417 : for (i = 0, camp = bd_xp->pField; i < bd_xp->nFields; i++, camp++)
428 : {
429 1226 : camp->AccumulatedBytes = bd_xp->BytesPerRecord;
430 1226 : bd_xp->BytesPerRecord += camp->BytesPerField;
431 1226 : if (camp->DesiredWidth == 0)
432 1226 : camp->DesiredWidth = camp->OriginalDesiredWidth =
433 1226 : MM_GetDefaultDesiredDBFFieldWidth(camp); //camp->BytesPerField;
434 1226 : if (camp->FieldType == 'C' &&
435 192 : camp->BytesPerField > MM_MAX_AMPLADA_CAMP_C_DBF_CLASSICA)
436 0 : cal_DBF_estesa = TRUE;
437 1226 : if (MM_VALID_EXTENDED_DBF_NAME ==
438 1226 : MM_ISExtendedNameBD_XP(camp->FieldName))
439 91 : cal_DBF_estesa = TRUE;
440 : }
441 :
442 191 : bd_xp->FirstRecordOffset = MM_CalculateBytesFirstRecordOffset(bd_xp);
443 :
444 191 : if (cal_DBF_estesa || bd_xp->nFields > MM_MAX_N_CAMPS_DBF_CLASSICA ||
445 167 : bd_xp->nRecords > UINT32_MAX)
446 24 : bd_xp->dbf_version = (MM_BYTE)MM_MARCA_VERSIO_1_DBF_ESTESA;
447 : else
448 167 : bd_xp->dbf_version = MM_MARCA_DBASE4;
449 191 : }
450 :
451 : static void
452 2105 : MM_InitializeOffsetExtendedFieldNameFields(struct MM_DATA_BASE_XP *bd_xp,
453 : MM_EXT_DBF_N_FIELDS i_camp)
454 : {
455 2105 : memset((char *)(&bd_xp->pField[i_camp].reserved_2) +
456 : MM_OFFSET_RESERVAT2_OFFSET_NOM_ESTES,
457 : 0, 4);
458 2105 : }
459 :
460 : static void
461 2105 : MM_InitializeBytesExtendedFieldNameFields(struct MM_DATA_BASE_XP *bd_xp,
462 : MM_EXT_DBF_N_FIELDS i_camp)
463 : {
464 2105 : memset((char *)(&bd_xp->pField[i_camp].reserved_2) +
465 : MM_OFFSET_RESERVED2_EXTENDED_NAME_SIZE,
466 : 0, 1);
467 2105 : }
468 :
469 91 : static short int MM_return_common_valid_DBF_field_name_string(char *szChain)
470 : {
471 : char *p;
472 91 : short int error_retornat = 0;
473 :
474 91 : if (!szChain)
475 0 : return 0;
476 : //strupr(szChain);
477 1204 : for (p = szChain; *p; p++)
478 : {
479 1113 : (*p) = (char)toupper((unsigned char)*p);
480 1113 : if ((*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_')
481 : ;
482 : else
483 : {
484 7 : *p = '_';
485 7 : error_retornat |= MM_FIELD_NAME_CHARACTER_INVALID;
486 : }
487 : }
488 91 : if (szChain[0] == '_')
489 : {
490 : // To avoid having field names starting by '_' this case is
491 : // substituted by a 0 (not a '\0').
492 0 : szChain[0] = '0';
493 0 : error_retornat |= MM_FIELD_NAME_FIRST_CHARACTER_;
494 : }
495 91 : return error_retornat;
496 : }
497 :
498 91 : static short int MM_ReturnValidClassicDBFFieldName(char *szChain)
499 : {
500 : size_t long_nom_camp;
501 91 : short int error_retornat = 0;
502 :
503 91 : long_nom_camp = strlen(szChain);
504 91 : if ((long_nom_camp < 1) ||
505 : (long_nom_camp >= MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF))
506 : {
507 89 : szChain[MM_MAX_LON_FIELD_NAME_DBF - 1] = '\0';
508 89 : error_retornat |= MM_FIELD_NAME_TOO_LONG;
509 : }
510 91 : error_retornat |= MM_return_common_valid_DBF_field_name_string(szChain);
511 91 : return error_retornat;
512 : }
513 :
514 : static MM_BOOLEAN
515 91 : MM_CheckClassicFieldNameEqual(const struct MM_DATA_BASE_XP *data_base_XP,
516 : const char *classical_name)
517 : {
518 : MM_EXT_DBF_N_FIELDS i;
519 :
520 1300 : for (i = 0; i < data_base_XP->nFields; i++)
521 : {
522 1209 : if ((strcasecmp(data_base_XP->pField[i].ClassicalDBFFieldName,
523 1209 : classical_name)) == 0 ||
524 1209 : (strcasecmp(data_base_XP->pField[i].FieldName, classical_name)) ==
525 : 0)
526 0 : return TRUE;
527 : }
528 91 : return FALSE;
529 : }
530 :
531 0 : static char *MM_GiveNewStringWithCharacterInFront(const char *text,
532 : char character)
533 : {
534 : char *ptr;
535 : size_t i;
536 :
537 0 : if (!text)
538 0 : return nullptr;
539 :
540 0 : i = strlen(text);
541 0 : if ((ptr = VSICalloc(1, i + 2)) == nullptr)
542 0 : return nullptr;
543 :
544 0 : *ptr = character;
545 0 : memcpy(ptr + 1, text, i + 1);
546 0 : return ptr;
547 : }
548 :
549 0 : static char *MM_SetSubIndexFieldNam(const char *nom_camp,
550 : MM_EXT_DBF_N_FIELDS index,
551 : size_t ampladamax)
552 : {
553 : char *NomCamp_SubIndex;
554 : char *_subindex;
555 : char subindex[19 + 1];
556 : size_t sizet_subindex;
557 : size_t sizet_nomcamp;
558 :
559 0 : NomCamp_SubIndex = VSICalloc(1, ampladamax);
560 0 : if (!NomCamp_SubIndex)
561 0 : return nullptr;
562 :
563 0 : CPLStrlcpy(NomCamp_SubIndex, nom_camp, ampladamax);
564 0 : NomCamp_SubIndex[ampladamax - 1] = '\0';
565 :
566 0 : snprintf(subindex, sizeof(subindex), sprintf_UINT64, (GUInt64)index);
567 :
568 0 : _subindex = MM_GiveNewStringWithCharacterInFront(subindex, '_');
569 0 : if (!_subindex)
570 : {
571 0 : VSIFree(NomCamp_SubIndex);
572 0 : return nullptr;
573 : }
574 :
575 0 : sizet_subindex = strlen(_subindex);
576 0 : sizet_nomcamp = strlen(NomCamp_SubIndex);
577 :
578 0 : if (sizet_nomcamp + sizet_subindex > ampladamax - 1)
579 0 : memcpy(NomCamp_SubIndex + ((ampladamax - 1) - sizet_subindex),
580 : _subindex, strlen(_subindex));
581 : else
582 0 : NomCamp_SubIndex = strcat(NomCamp_SubIndex, _subindex);
583 :
584 0 : VSIFree(_subindex);
585 :
586 0 : return NomCamp_SubIndex;
587 : }
588 :
589 : MM_FIRST_RECORD_OFFSET_TYPE
590 771 : MM_GiveOffsetExtendedFieldName(const struct MM_FIELD *camp)
591 : {
592 : MM_FIRST_RECORD_OFFSET_TYPE offset_nom_camp;
593 :
594 771 : memcpy(&offset_nom_camp,
595 771 : (char *)(&camp->reserved_2) + MM_OFFSET_RESERVAT2_OFFSET_NOM_ESTES,
596 : 4);
597 771 : return offset_nom_camp;
598 : }
599 :
600 308 : int MM_WriteNRecordsMMBD_XPFile(struct MMAdmDatabase *MMAdmDB)
601 : {
602 308 : if (!MMAdmDB->pMMBDXP || !MMAdmDB->pMMBDXP->pfDataBase)
603 0 : return 0;
604 :
605 : // Updating number of features in features table
606 308 : VSIFSeekL(MMAdmDB->pMMBDXP->pfDataBase, MM_FIRST_OFFSET_to_N_RECORDS,
607 : SEEK_SET);
608 :
609 308 : if (MMAdmDB->pMMBDXP->nRecords > UINT32_MAX)
610 : {
611 0 : MMAdmDB->pMMBDXP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
612 : }
613 : else
614 : {
615 308 : MMAdmDB->pMMBDXP->dbf_version = MM_MARCA_DBASE4;
616 : }
617 :
618 : {
619 308 : GUInt32 nRecords32LowBits =
620 308 : (GUInt32)(MMAdmDB->pMMBDXP->nRecords & UINT32_MAX);
621 308 : if (VSIFWriteL(&nRecords32LowBits, 4, 1,
622 308 : MMAdmDB->pMMBDXP->pfDataBase) != 1)
623 0 : return 1;
624 : }
625 :
626 308 : VSIFSeekL(MMAdmDB->pMMBDXP->pfDataBase, MM_SECOND_OFFSET_to_N_RECORDS,
627 : SEEK_SET);
628 308 : if (MMAdmDB->pMMBDXP->dbf_version == MM_MARCA_VERSIO_1_DBF_ESTESA)
629 : {
630 : /* from 16 to 19, position MM_SECOND_OFFSET_to_N_RECORDS */
631 0 : GUInt32 nRecords32HighBits =
632 0 : (GUInt32)(MMAdmDB->pMMBDXP->nRecords >> 32);
633 0 : if (VSIFWriteL(&nRecords32HighBits, 4, 1,
634 0 : MMAdmDB->pMMBDXP->pfDataBase) != 1)
635 0 : return 1;
636 :
637 : /* from 20 to 27 */
638 0 : if (VSIFWriteL(&(MMAdmDB->pMMBDXP->dbf_on_a_LAN), 8, 1,
639 0 : MMAdmDB->pMMBDXP->pfDataBase) != 1)
640 0 : return 1;
641 : }
642 : else
643 : {
644 308 : if (VSIFWriteL(&(MMAdmDB->pMMBDXP->dbf_on_a_LAN), 12, 1,
645 308 : MMAdmDB->pMMBDXP->pfDataBase) != 1)
646 0 : return 1;
647 : }
648 :
649 308 : return 0;
650 : }
651 :
652 : static MM_BOOLEAN
653 308 : MM_OpenIfNeededAndUpdateEntireHeader(struct MM_DATA_BASE_XP *data_base_XP)
654 : {
655 : MM_BYTE variable_byte;
656 308 : MM_EXT_DBF_N_FIELDS i, j = 0;
657 308 : char zero[11] = {0};
658 308 : const MM_BYTE byte_zero = 0;
659 308 : char ModeLectura_previ[4] = "";
660 : MM_FIRST_RECORD_OFFSET_TYPE bytes_acumulats;
661 : MM_BYTE name_size;
662 : int estat;
663 : char nom_camp[MM_MAX_LON_FIELD_NAME_DBF];
664 : size_t retorn_fwrite;
665 :
666 308 : if (!data_base_XP)
667 0 : return FALSE;
668 :
669 308 : if (data_base_XP->pfDataBase == nullptr)
670 : {
671 191 : strcpy(ModeLectura_previ, data_base_XP->ReadingMode);
672 191 : strcpy(data_base_XP->ReadingMode, "wb+");
673 :
674 191 : if ((data_base_XP->pfDataBase = VSIFOpenL(data_base_XP->szFileName,
675 191 : data_base_XP->ReadingMode)) ==
676 : nullptr)
677 : {
678 0 : return FALSE;
679 : }
680 : }
681 : else
682 : {
683 : // If it's open we just update the header
684 117 : VSIFSeekL(data_base_XP->pfDataBase, 0, SEEK_SET);
685 : }
686 :
687 308 : if ((data_base_XP->nFields) > MM_MAX_N_CAMPS_DBF_CLASSICA)
688 0 : data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
689 308 : else if ((data_base_XP->nRecords) > UINT32_MAX)
690 0 : data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
691 : else
692 : {
693 308 : if (data_base_XP->dbf_version == MM_MARCA_VERSIO_1_DBF_ESTESA)
694 24 : data_base_XP->dbf_version = MM_MARCA_DBASE4;
695 2240 : for (i = 0; i < data_base_XP->nFields; i++)
696 : {
697 2022 : if (data_base_XP->pField[i].FieldType == 'C' &&
698 348 : data_base_XP->pField[i].BytesPerField >
699 : MM_MAX_AMPLADA_CAMP_C_DBF_CLASSICA)
700 : {
701 0 : data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
702 0 : break;
703 : }
704 2022 : if (MM_VALID_EXTENDED_DBF_NAME ==
705 2022 : MM_ISExtendedNameBD_XP(data_base_XP->pField[i].FieldName))
706 : {
707 90 : data_base_XP->dbf_version = MM_MARCA_VERSIO_1_DBF_ESTESA;
708 90 : break;
709 : }
710 : }
711 : }
712 :
713 : // Writing header
714 308 : VSIFSeekL(data_base_XP->pfDataBase, 0, SEEK_SET);
715 :
716 : /* Byte 0 */
717 308 : if (VSIFWriteL(&(data_base_XP->dbf_version), 1, 1,
718 : data_base_XP->pfDataBase) != 1)
719 : {
720 0 : VSIFCloseL(data_base_XP->pfDataBase);
721 0 : data_base_XP->pfDataBase = nullptr;
722 0 : return FALSE;
723 : }
724 :
725 : /* MM_BYTE from 1 to 3 */
726 308 : variable_byte = (MM_BYTE)(data_base_XP->year - 1900);
727 308 : if (VSIFWriteL(&variable_byte, 1, 1, data_base_XP->pfDataBase) != 1)
728 : {
729 0 : VSIFCloseL(data_base_XP->pfDataBase);
730 0 : data_base_XP->pfDataBase = nullptr;
731 0 : return FALSE;
732 : }
733 308 : if (VSIFWriteL(&(data_base_XP->month), 1, 1, data_base_XP->pfDataBase) != 1)
734 : {
735 0 : VSIFCloseL(data_base_XP->pfDataBase);
736 0 : data_base_XP->pfDataBase = nullptr;
737 0 : return FALSE;
738 : }
739 308 : if (VSIFWriteL(&(data_base_XP->day), 1, 1, data_base_XP->pfDataBase) != 1)
740 : {
741 0 : VSIFCloseL(data_base_XP->pfDataBase);
742 0 : data_base_XP->pfDataBase = nullptr;
743 0 : return FALSE;
744 : }
745 :
746 : /* from 4 a 7, position MM_FIRST_OFFSET_to_N_RECORDS */
747 : {
748 308 : GUInt32 nRecords32LowBits =
749 308 : (GUInt32)(data_base_XP->nRecords & UINT32_MAX);
750 308 : if (VSIFWriteL(&nRecords32LowBits, 4, 1, data_base_XP->pfDataBase) != 1)
751 : {
752 0 : VSIFCloseL(data_base_XP->pfDataBase);
753 0 : data_base_XP->pfDataBase = nullptr;
754 0 : return FALSE;
755 : }
756 : }
757 :
758 : /* from 8 a 9, position MM_PRIMER_OFFSET_a_OFFSET_1a_FITXA */
759 308 : if (VSIFWriteL(&(data_base_XP->FirstRecordOffset), 2, 1,
760 : data_base_XP->pfDataBase) != 1)
761 : {
762 0 : VSIFCloseL(data_base_XP->pfDataBase);
763 0 : data_base_XP->pfDataBase = nullptr;
764 0 : return FALSE;
765 : }
766 : /* from 10 to 11, & from 12 to 13 */
767 308 : if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version))
768 : {
769 90 : if (VSIFWriteL(&(data_base_XP->BytesPerRecord),
770 : sizeof(MM_ACCUMULATED_BYTES_TYPE_DBF), 1,
771 : data_base_XP->pfDataBase) != 1)
772 : {
773 0 : VSIFCloseL(data_base_XP->pfDataBase);
774 0 : data_base_XP->pfDataBase = nullptr;
775 0 : return FALSE;
776 : }
777 : }
778 : else
779 : {
780 : /* from 10 to 11 */
781 218 : if (VSIFWriteL(&(data_base_XP->BytesPerRecord), 2, 1,
782 : data_base_XP->pfDataBase) != 1)
783 : {
784 0 : VSIFCloseL(data_base_XP->pfDataBase);
785 0 : data_base_XP->pfDataBase = nullptr;
786 0 : return FALSE;
787 : }
788 : /* from 12 to 13 */
789 218 : if (VSIFWriteL(&(data_base_XP->reserved_1), 2, 1,
790 : data_base_XP->pfDataBase) != 1)
791 : {
792 0 : VSIFCloseL(data_base_XP->pfDataBase);
793 0 : data_base_XP->pfDataBase = nullptr;
794 0 : return FALSE;
795 : }
796 : }
797 : /* byte 14 */
798 308 : if (VSIFWriteL(&(data_base_XP->transaction_flag), 1, 1,
799 : data_base_XP->pfDataBase) != 1)
800 : {
801 0 : VSIFCloseL(data_base_XP->pfDataBase);
802 0 : data_base_XP->pfDataBase = nullptr;
803 0 : return FALSE;
804 : }
805 : /* byte 15 */
806 308 : if (VSIFWriteL(&(data_base_XP->encryption_flag), 1, 1,
807 : data_base_XP->pfDataBase) != 1)
808 : {
809 0 : VSIFCloseL(data_base_XP->pfDataBase);
810 0 : data_base_XP->pfDataBase = nullptr;
811 0 : return FALSE;
812 : }
813 :
814 : /* from 16 to 27 */
815 308 : if (data_base_XP->nRecords > UINT32_MAX)
816 : {
817 : /* from 16 to 19, position MM_SECOND_OFFSET_to_N_RECORDS */
818 0 : GUInt32 nRecords32HighBits = (GUInt32)(data_base_XP->nRecords >> 32);
819 0 : if (VSIFWriteL(&nRecords32HighBits, 4, 1, data_base_XP->pfDataBase) !=
820 : 1)
821 : {
822 0 : VSIFCloseL(data_base_XP->pfDataBase);
823 0 : data_base_XP->pfDataBase = nullptr;
824 0 : return FALSE;
825 : }
826 :
827 : /* from 20 to 27 */
828 0 : if (VSIFWriteL(&(data_base_XP->dbf_on_a_LAN), 8, 1,
829 : data_base_XP->pfDataBase) != 1)
830 : {
831 0 : VSIFCloseL(data_base_XP->pfDataBase);
832 0 : data_base_XP->pfDataBase = nullptr;
833 0 : return FALSE;
834 : }
835 : }
836 : else
837 : {
838 : /* from 16 to 27 */
839 308 : if (VSIFWriteL(&(data_base_XP->dbf_on_a_LAN), 12, 1,
840 : data_base_XP->pfDataBase) != 1)
841 : {
842 0 : VSIFCloseL(data_base_XP->pfDataBase);
843 0 : data_base_XP->pfDataBase = nullptr;
844 0 : return FALSE;
845 : }
846 : }
847 : /* byte 28 */
848 308 : if (VSIFWriteL(&(data_base_XP->MDX_flag), 1, 1, data_base_XP->pfDataBase) !=
849 : 1)
850 : {
851 0 : VSIFCloseL(data_base_XP->pfDataBase);
852 0 : data_base_XP->pfDataBase = nullptr;
853 0 : return FALSE;
854 : }
855 :
856 : /* Byte 29 */
857 308 : if (VSIFWriteL(&(data_base_XP->CharSet), 1, 1, data_base_XP->pfDataBase) !=
858 : 1)
859 : {
860 0 : VSIFCloseL(data_base_XP->pfDataBase);
861 0 : data_base_XP->pfDataBase = nullptr;
862 0 : return FALSE;
863 : }
864 :
865 : /* Bytes from 30 to 31, in position MM_SEGON_OFFSET_a_OFFSET_1a_FITXA */
866 308 : if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version))
867 : {
868 90 : if (VSIFWriteL(((char *)&(data_base_XP->FirstRecordOffset)) + 2, 2, 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 : }
876 : else
877 : {
878 218 : if (VSIFWriteL(&(data_base_XP->reserved_2), 2, 1,
879 : data_base_XP->pfDataBase) != 1)
880 : {
881 0 : VSIFCloseL(data_base_XP->pfDataBase);
882 0 : data_base_XP->pfDataBase = nullptr;
883 0 : return FALSE;
884 : }
885 : }
886 :
887 : /* At 32th byte fields description begins */
888 : /* Every description is 32 bytes long */
889 308 : bytes_acumulats = 32 + 32 * (data_base_XP->nFields) + 1;
890 :
891 2852 : for (i = 0; i < data_base_XP->nFields; i++)
892 : {
893 : /* Bytes from 0 to 10 -> Field name, \0 finished */
894 2544 : estat = MM_ISExtendedNameBD_XP(data_base_XP->pField[i].FieldName);
895 2544 : if (estat == NM_CLASSICAL_DBF_AND_VALID_NAME ||
896 : estat == MM_DBF_NAME_LOWERCASE_AND_VALID)
897 : {
898 2105 : j = (short)strlen(data_base_XP->pField[i].FieldName);
899 :
900 2105 : retorn_fwrite = VSIFWriteL(&data_base_XP->pField[i].FieldName, 1, j,
901 : data_base_XP->pfDataBase);
902 2105 : if (retorn_fwrite != (size_t)j)
903 : {
904 0 : VSIFCloseL(data_base_XP->pfDataBase);
905 0 : data_base_XP->pfDataBase = nullptr;
906 0 : return FALSE;
907 : }
908 2105 : MM_InitializeOffsetExtendedFieldNameFields(data_base_XP, i);
909 2105 : MM_InitializeBytesExtendedFieldNameFields(data_base_XP, i);
910 : }
911 439 : else if (estat == MM_VALID_EXTENDED_DBF_NAME)
912 : {
913 439 : if (*(data_base_XP->pField[i].ClassicalDBFFieldName) == '\0')
914 : {
915 : char nom_temp[MM_MAX_LON_FIELD_NAME_DBF];
916 :
917 91 : CPLStrlcpy(nom_temp, data_base_XP->pField[i].FieldName,
918 : MM_MAX_LON_FIELD_NAME_DBF);
919 91 : MM_ReturnValidClassicDBFFieldName(nom_temp);
920 91 : nom_temp[MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF - 1] = '\0';
921 91 : if ((MM_CheckClassicFieldNameEqual(data_base_XP, nom_temp)) ==
922 : TRUE)
923 : {
924 : char *c;
925 :
926 0 : c = MM_SetSubIndexFieldNam(
927 : nom_temp, i, MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF);
928 :
929 0 : if (c)
930 : {
931 0 : j = 0;
932 0 : while (MM_CheckClassicFieldNameEqual(data_base_XP, c) ==
933 0 : TRUE &&
934 0 : j < data_base_XP->nFields)
935 : {
936 0 : VSIFree(c);
937 0 : c = MM_SetSubIndexFieldNam(
938 : nom_temp, ++j,
939 : MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF);
940 : }
941 0 : if (c)
942 : {
943 0 : CPLStrlcpy(
944 0 : data_base_XP->pField[i].ClassicalDBFFieldName,
945 : c,
946 : sizeof(data_base_XP->pField[i]
947 : .ClassicalDBFFieldName));
948 0 : VSIFree(c);
949 : }
950 : }
951 : }
952 : else
953 91 : CPLStrlcpy(
954 91 : data_base_XP->pField[i].ClassicalDBFFieldName, nom_temp,
955 : sizeof(data_base_XP->pField[i].ClassicalDBFFieldName));
956 : }
957 :
958 : // This is a 11-byte fixed size field consisting of the filename
959 : // and it's been padding calculated some next lines.
960 439 : j = (short)strlen(data_base_XP->pField[i].ClassicalDBFFieldName);
961 :
962 : retorn_fwrite =
963 439 : VSIFWriteL(&data_base_XP->pField[i].ClassicalDBFFieldName, 1, j,
964 : data_base_XP->pfDataBase);
965 439 : if (retorn_fwrite != (size_t)j)
966 : {
967 0 : VSIFCloseL(data_base_XP->pfDataBase);
968 0 : data_base_XP->pfDataBase = nullptr;
969 0 : return FALSE;
970 : }
971 :
972 : name_size =
973 439 : MM_CalculateBytesExtendedFieldName(data_base_XP->pField + i);
974 439 : MM_EscriuOffsetNomEstesBD_XP(data_base_XP, i, bytes_acumulats);
975 439 : bytes_acumulats += name_size;
976 : }
977 : else
978 : {
979 0 : VSIFCloseL(data_base_XP->pfDataBase);
980 0 : data_base_XP->pfDataBase = nullptr;
981 0 : return FALSE;
982 : }
983 :
984 2544 : if (VSIFWriteL(zero, 1, 11 - j, data_base_XP->pfDataBase) !=
985 2544 : 11 - (size_t)j)
986 : {
987 0 : VSIFCloseL(data_base_XP->pfDataBase);
988 0 : data_base_XP->pfDataBase = nullptr;
989 0 : return FALSE;
990 : }
991 : /* Byte 11, Field type */
992 2544 : if (VSIFWriteL(&data_base_XP->pField[i].FieldType, 1, 1,
993 : data_base_XP->pfDataBase) != 1)
994 : {
995 0 : VSIFCloseL(data_base_XP->pfDataBase);
996 0 : data_base_XP->pfDataBase = nullptr;
997 0 : return FALSE;
998 : }
999 : /* Bytes 12 to 15 --> Reserved */
1000 2544 : if (VSIFWriteL(&data_base_XP->pField[i].reserved_1, 4, 1,
1001 : data_base_XP->pfDataBase) != 1)
1002 : {
1003 0 : VSIFCloseL(data_base_XP->pfDataBase);
1004 0 : data_base_XP->pfDataBase = nullptr;
1005 0 : return FALSE;
1006 : }
1007 : /* Byte 16, or OFFSET_BYTESxCAMP_CAMP_CLASSIC --> BytesPerField */
1008 2544 : if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version) &&
1009 1192 : data_base_XP->pField[i].FieldType == 'C')
1010 : {
1011 201 : if (VSIFWriteL((void *)&byte_zero, 1, 1,
1012 : data_base_XP->pfDataBase) != 1)
1013 : {
1014 0 : VSIFCloseL(data_base_XP->pfDataBase);
1015 0 : data_base_XP->pfDataBase = nullptr;
1016 0 : return FALSE;
1017 : }
1018 : }
1019 : else
1020 : {
1021 2343 : if (VSIFWriteL(&data_base_XP->pField[i].BytesPerField, 1, 1,
1022 : data_base_XP->pfDataBase) != 1)
1023 : {
1024 0 : VSIFCloseL(data_base_XP->pfDataBase);
1025 0 : data_base_XP->pfDataBase = nullptr;
1026 0 : return FALSE;
1027 : }
1028 : }
1029 : /* 17th byte 17 --> In fields of type 'N' and 'F' indicates decimal places.*/
1030 2544 : if (data_base_XP->pField[i].FieldType == 'N' ||
1031 716 : data_base_XP->pField[i].FieldType == 'F')
1032 : {
1033 1828 : if (VSIFWriteL(&data_base_XP->pField[i].DecimalsIfFloat, 1, 1,
1034 : data_base_XP->pfDataBase) != 1)
1035 : {
1036 0 : VSIFCloseL(data_base_XP->pfDataBase);
1037 0 : data_base_XP->pfDataBase = nullptr;
1038 0 : return FALSE;
1039 : }
1040 : }
1041 : else
1042 : {
1043 716 : if (VSIFWriteL(zero, 1, 1, data_base_XP->pfDataBase) != 1)
1044 : {
1045 0 : VSIFCloseL(data_base_XP->pfDataBase);
1046 0 : data_base_XP->pfDataBase = nullptr;
1047 0 : return FALSE;
1048 : }
1049 : }
1050 2544 : if (MM_ES_DBF_ESTESA(data_base_XP->dbf_version) &&
1051 1192 : data_base_XP->pField[i].FieldType == 'C')
1052 : {
1053 : /* Bytes from 18 to 20 --> Reserved */
1054 201 : if (VSIFWriteL(&data_base_XP->pField[i].reserved_2, 20 - 18 + 1, 1,
1055 : data_base_XP->pfDataBase) != 1)
1056 : {
1057 0 : VSIFCloseL(data_base_XP->pfDataBase);
1058 0 : data_base_XP->pfDataBase = nullptr;
1059 0 : return FALSE;
1060 : }
1061 : /* Bytes from 21 to 24 --> OFFSET_BYTESxCAMP_CAMP_ESPECIAL, special fields, like C
1062 : in extended DBF */
1063 201 : if (VSIFWriteL(&data_base_XP->pField[i].BytesPerField,
1064 : sizeof(MM_BYTES_PER_FIELD_TYPE_DBF), 1,
1065 : data_base_XP->pfDataBase) != 1)
1066 : {
1067 0 : VSIFCloseL(data_base_XP->pfDataBase);
1068 0 : data_base_XP->pfDataBase = nullptr;
1069 0 : return FALSE;
1070 : }
1071 :
1072 : /* Bytes from 25 to 30 --> Reserved */
1073 201 : if (VSIFWriteL(&data_base_XP->pField[i].reserved_2[25 - 18],
1074 : 30 - 25 + 1, 1, data_base_XP->pfDataBase) != 1)
1075 : {
1076 0 : VSIFCloseL(data_base_XP->pfDataBase);
1077 0 : data_base_XP->pfDataBase = nullptr;
1078 0 : return FALSE;
1079 : }
1080 : }
1081 : else
1082 : {
1083 : /* Bytes de 21 a 24 --> OFFSET_BYTESxCAMP_CAMP_ESPECIAL, special fields, like C */
1084 2343 : memset(data_base_XP->pField[i].reserved_2 +
1085 : MM_OFFSET_RESERVAT2_BYTESxCAMP_CAMP_ESPECIAL,
1086 : '\0', 4);
1087 : /* Bytes from 18 to 30 --> Reserved */
1088 2343 : if (VSIFWriteL(&data_base_XP->pField[i].reserved_2, 13, 1,
1089 : data_base_XP->pfDataBase) != 1)
1090 : {
1091 0 : VSIFCloseL(data_base_XP->pfDataBase);
1092 0 : data_base_XP->pfDataBase = nullptr;
1093 0 : return FALSE;
1094 : }
1095 : }
1096 : /* Byte 31 --> MDX flag. */
1097 2544 : if (VSIFWriteL(&data_base_XP->pField[i].MDX_field_flag, 1, 1,
1098 : data_base_XP->pfDataBase) != 1)
1099 : {
1100 0 : VSIFCloseL(data_base_XP->pfDataBase);
1101 0 : data_base_XP->pfDataBase = nullptr;
1102 0 : return FALSE;
1103 : }
1104 : }
1105 :
1106 308 : variable_byte = 13;
1107 308 : if (VSIFWriteL(&variable_byte, 1, 1, data_base_XP->pfDataBase) != 1)
1108 : {
1109 0 : VSIFCloseL(data_base_XP->pfDataBase);
1110 0 : data_base_XP->pfDataBase = nullptr;
1111 0 : return FALSE;
1112 : }
1113 :
1114 308 : if (data_base_XP->FirstRecordOffset != bytes_acumulats)
1115 : {
1116 0 : VSIFCloseL(data_base_XP->pfDataBase);
1117 0 : data_base_XP->pfDataBase = nullptr;
1118 0 : return FALSE;
1119 : }
1120 :
1121 : // Extended fields
1122 2852 : for (i = 0; i < data_base_XP->nFields; i++)
1123 : {
1124 2544 : if (MM_VALID_EXTENDED_DBF_NAME ==
1125 2544 : MM_ISExtendedNameBD_XP(data_base_XP->pField[i].FieldName))
1126 : {
1127 439 : bytes_acumulats =
1128 439 : MM_GiveOffsetExtendedFieldName(data_base_XP->pField + i);
1129 439 : name_size = MM_DonaBytesNomEstesCamp(data_base_XP->pField + i);
1130 :
1131 439 : VSIFSeekL(data_base_XP->pfDataBase, bytes_acumulats, SEEK_SET);
1132 :
1133 439 : strcpy(nom_camp, data_base_XP->pField[i].FieldName);
1134 : //CanviaJocCaracPerEscriureDBF(nom_camp, JocCaracDBFaMM(data_base_XP->CharSet, ParMM.JocCaracDBFPerDefecte));
1135 :
1136 : retorn_fwrite =
1137 439 : VSIFWriteL(nom_camp, 1, name_size, data_base_XP->pfDataBase);
1138 :
1139 439 : if (retorn_fwrite != (size_t)name_size)
1140 : {
1141 0 : VSIFCloseL(data_base_XP->pfDataBase);
1142 0 : data_base_XP->pfDataBase = nullptr;
1143 0 : return FALSE;
1144 : }
1145 : }
1146 : }
1147 :
1148 308 : return TRUE;
1149 : } /* End of MM_OpenIfNeededAndUpdateEntireHeader() */
1150 :
1151 191 : MM_BOOLEAN MM_CreateAndOpenDBFFile(struct MM_DATA_BASE_XP *bd_xp,
1152 : const char *NomFitxer)
1153 : {
1154 : time_t currentTime;
1155 :
1156 191 : if (!NomFitxer || MMIsEmptyString(NomFitxer) || !bd_xp)
1157 0 : return FALSE;
1158 :
1159 191 : MM_CheckDBFHeader(bd_xp);
1160 :
1161 : // Setting the current date
1162 191 : currentTime = time(nullptr);
1163 :
1164 : struct tm ltime;
1165 191 : VSILocalTime(¤tTime, <ime);
1166 :
1167 191 : bd_xp->year = (short int)(ltime.tm_year + 1900);
1168 191 : bd_xp->month = (MM_BYTE)(ltime.tm_mon + 1);
1169 191 : bd_xp->day = (MM_BYTE)ltime.tm_mday;
1170 :
1171 191 : CPLStrlcpy(bd_xp->szFileName, NomFitxer, sizeof(bd_xp->szFileName));
1172 191 : return MM_OpenIfNeededAndUpdateEntireHeader(bd_xp);
1173 : }
1174 :
1175 307 : void MM_ReleaseMainFields(struct MM_DATA_BASE_XP *data_base_XP)
1176 : {
1177 : MM_EXT_DBF_N_FIELDS i;
1178 : size_t j;
1179 : char **szChain;
1180 :
1181 307 : if (data_base_XP->pField)
1182 : {
1183 2613 : for (i = 0; i < data_base_XP->nFields; i++)
1184 : {
1185 11535 : for (j = 0; j < MM_NUM_IDIOMES_MD_MULTIDIOMA; j++)
1186 : {
1187 9228 : szChain = data_base_XP->pField[i].Separator;
1188 9228 : if (szChain[j])
1189 : {
1190 0 : VSIFree(szChain[j]);
1191 0 : szChain[j] = nullptr;
1192 : }
1193 : }
1194 : }
1195 306 : VSIFree(data_base_XP->pField);
1196 306 : data_base_XP->pField = nullptr;
1197 306 : data_base_XP->nFields = 0;
1198 : }
1199 307 : return;
1200 : }
1201 :
1202 : // READING THE HEADER OF AN EXTENDED DBF
1203 : // Free with MM_ReleaseDBFHeader()
1204 116 : int MM_ReadExtendedDBFHeaderFromFile(const char *szFileName,
1205 : struct MM_DATA_BASE_XP *pMMBDXP,
1206 : const char *pszRelFile)
1207 : {
1208 : MM_BYTE variable_byte;
1209 : VSILFILE *pf;
1210 : unsigned short int two_bytes;
1211 : MM_EXT_DBF_N_FIELDS nIField;
1212 : uint16_t offset_primera_fitxa;
1213 116 : MM_FIRST_RECORD_OFFSET_TYPE offset_fals = 0;
1214 116 : MM_BOOLEAN incoherent_record_size = FALSE;
1215 : MM_BYTE un_byte;
1216 : MM_BYTES_PER_FIELD_TYPE_DBF bytes_per_camp;
1217 : MM_BYTE tretze_bytes[13];
1218 : MM_FIRST_RECORD_OFFSET_TYPE offset_possible;
1219 116 : MM_BYTE some_problems_when_reading = 0;
1220 116 : MM_FILE_OFFSET offset_reintent = 0; // For retrying
1221 : char cpg_file[MM_CPL_PATH_BUF_SIZE];
1222 : char *pszDesc;
1223 : char section[MM_MAX_LON_FIELD_NAME_DBF + 25]; // TAULA_PRINCIPAL:field_name
1224 : GUInt32 nRecords32LowBits;
1225 : char *pszString;
1226 :
1227 116 : if (!szFileName || !pMMBDXP)
1228 0 : return 1;
1229 :
1230 116 : CPLStrlcpy(pMMBDXP->szFileName, szFileName, sizeof(pMMBDXP->szFileName));
1231 116 : strcpy(pMMBDXP->ReadingMode, "rb");
1232 :
1233 116 : if ((pMMBDXP->pfDataBase =
1234 116 : VSIFOpenL(pMMBDXP->szFileName, pMMBDXP->ReadingMode)) == nullptr)
1235 1 : return 1;
1236 :
1237 115 : pf = pMMBDXP->pfDataBase;
1238 :
1239 115 : VSIFSeekL(pf, 0, SEEK_SET);
1240 : /* ====== Header reading (32 bytes) =================== */
1241 115 : offset_primera_fitxa = 0;
1242 :
1243 230 : if (1 != VSIFReadL(&(pMMBDXP->dbf_version), 1, 1, pf) ||
1244 230 : 1 != VSIFReadL(&variable_byte, 1, 1, pf) ||
1245 230 : 1 != VSIFReadL(&(pMMBDXP->month), 1, 1, pf) ||
1246 115 : 1 != VSIFReadL(&(pMMBDXP->day), 1, 1, pf))
1247 : {
1248 0 : fclose_and_nullify(&pMMBDXP->pfDataBase);
1249 0 : return 1;
1250 : }
1251 :
1252 115 : if (1 != VSIFReadL(&nRecords32LowBits, 4, 1, pf))
1253 : {
1254 0 : fclose_and_nullify(&pMMBDXP->pfDataBase);
1255 0 : return 1;
1256 : }
1257 :
1258 115 : if (1 != VSIFReadL(&offset_primera_fitxa, 2, 1, pf))
1259 : {
1260 0 : fclose_and_nullify(&pMMBDXP->pfDataBase);
1261 0 : return 1;
1262 : }
1263 :
1264 115 : pMMBDXP->year = (short)(1900 + variable_byte);
1265 115 : reintenta_lectura_per_si_error_CreaCampBD_XP:
1266 :
1267 115 : if (some_problems_when_reading > 0)
1268 : {
1269 0 : if (!MM_ES_DBF_ESTESA(pMMBDXP->dbf_version))
1270 : {
1271 0 : offset_fals =
1272 0 : offset_primera_fitxa & (MM_FIRST_RECORD_OFFSET_TYPE)(~31);
1273 : }
1274 : }
1275 : else
1276 115 : offset_reintent = VSIFTellL(pf);
1277 :
1278 230 : if (1 != VSIFReadL(&two_bytes, 2, 1, pf) ||
1279 230 : 1 != VSIFReadL(&(pMMBDXP->reserved_1), 2, 1, pf) ||
1280 230 : 1 != VSIFReadL(&(pMMBDXP->transaction_flag), 1, 1, pf) ||
1281 230 : 1 != VSIFReadL(&(pMMBDXP->encryption_flag), 1, 1, pf) ||
1282 115 : 1 != VSIFReadL(&(pMMBDXP->dbf_on_a_LAN), 12, 1, pf))
1283 : {
1284 0 : VSIFree(pMMBDXP->pField);
1285 0 : pMMBDXP->pField = nullptr;
1286 0 : pMMBDXP->nFields = 0;
1287 0 : fclose_and_nullify(&pMMBDXP->pfDataBase);
1288 0 : return 1;
1289 : }
1290 :
1291 115 : if (MM_ES_DBF_ESTESA(pMMBDXP->dbf_version))
1292 : {
1293 : GUInt32 nRecords32HighBits;
1294 :
1295 : // Getting 4 bytes of the 8 bytes variable
1296 38 : memcpy(&nRecords32HighBits, &pMMBDXP->dbf_on_a_LAN, 4);
1297 :
1298 : // Getting other 4 bytes of the 8 bytes variable
1299 : // The cast to GUInt64 of the high 32 bits is important to
1300 : // make sure the left bit shift is done correctly
1301 38 : pMMBDXP->nRecords =
1302 38 : ((GUInt64)nRecords32HighBits << 32) | nRecords32LowBits;
1303 : }
1304 : else
1305 77 : pMMBDXP->nRecords = nRecords32LowBits;
1306 :
1307 230 : if (1 != VSIFReadL(&(pMMBDXP->MDX_flag), 1, 1, pf) ||
1308 230 : 1 != VSIFReadL(&(pMMBDXP->CharSet), 1, 1, pf) ||
1309 115 : 1 != VSIFReadL(&(pMMBDXP->reserved_2), 2, 1, pf))
1310 : {
1311 0 : VSIFree(pMMBDXP->pField);
1312 0 : pMMBDXP->pField = nullptr;
1313 0 : pMMBDXP->nFields = 0;
1314 0 : fclose_and_nullify(&pMMBDXP->pfDataBase);
1315 0 : return 1;
1316 : }
1317 :
1318 : // Checking for a cpg file
1319 115 : if (pMMBDXP->CharSet == 0)
1320 : {
1321 : VSILFILE *f_cpg;
1322 : char charset_cpg[11];
1323 :
1324 3 : strcpy(cpg_file, pMMBDXP->szFileName);
1325 3 : CPLStrlcpy(cpg_file, CPLResetExtension(cpg_file, "cpg"),
1326 : sizeof(cpg_file));
1327 3 : f_cpg = VSIFOpenL(cpg_file, "r");
1328 3 : if (f_cpg)
1329 : {
1330 : char *p;
1331 : size_t read_bytes;
1332 0 : VSIFSeekL(f_cpg, 0L, SEEK_SET);
1333 0 : if (11 > (read_bytes = VSIFReadL(charset_cpg, 1, 10, f_cpg)))
1334 : {
1335 0 : charset_cpg[read_bytes] = '\0';
1336 0 : p = MM_stristr(charset_cpg, "UTF-8");
1337 0 : if (p)
1338 0 : pMMBDXP->CharSet = MM_JOC_CARAC_UTF8_DBF;
1339 0 : p = MM_stristr(charset_cpg, "UTF8");
1340 0 : if (p)
1341 0 : pMMBDXP->CharSet = MM_JOC_CARAC_UTF8_DBF;
1342 0 : p = MM_stristr(charset_cpg, "ISO-8859-1");
1343 0 : if (p)
1344 0 : pMMBDXP->CharSet = MM_JOC_CARAC_ANSI_DBASE;
1345 : }
1346 0 : VSIFCloseL(f_cpg);
1347 : }
1348 : }
1349 115 : if (MM_ES_DBF_ESTESA(pMMBDXP->dbf_version))
1350 : {
1351 : unsigned short FirstRecordOffsetLow16Bits;
1352 : unsigned short FirstRecordOffsetHigh16Bits;
1353 : GUInt32 nTmp;
1354 :
1355 38 : memcpy(&FirstRecordOffsetLow16Bits, &offset_primera_fitxa, 2);
1356 38 : memcpy(&FirstRecordOffsetHigh16Bits, &pMMBDXP->reserved_2, 2);
1357 :
1358 38 : nTmp = ((GUInt32)FirstRecordOffsetHigh16Bits << 16) |
1359 : FirstRecordOffsetLow16Bits;
1360 38 : if (nTmp > INT32_MAX)
1361 : {
1362 0 : VSIFree(pMMBDXP->pField);
1363 0 : pMMBDXP->pField = nullptr;
1364 0 : pMMBDXP->nFields = 0;
1365 0 : fclose_and_nullify(&pMMBDXP->pfDataBase);
1366 0 : return 1;
1367 : }
1368 38 : pMMBDXP->FirstRecordOffset = (MM_FIRST_RECORD_OFFSET_TYPE)nTmp;
1369 :
1370 38 : if (some_problems_when_reading > 0)
1371 0 : offset_fals = pMMBDXP->FirstRecordOffset;
1372 :
1373 38 : memcpy(&FirstRecordOffsetLow16Bits, &two_bytes, 2);
1374 38 : memcpy(&FirstRecordOffsetHigh16Bits, &pMMBDXP->reserved_1, 2);
1375 :
1376 38 : pMMBDXP->BytesPerRecord = ((GUInt32)FirstRecordOffsetHigh16Bits << 16) |
1377 : FirstRecordOffsetLow16Bits;
1378 : }
1379 : else
1380 : {
1381 77 : pMMBDXP->FirstRecordOffset = offset_primera_fitxa;
1382 77 : pMMBDXP->BytesPerRecord = two_bytes;
1383 : }
1384 :
1385 : /* ====== Record structure ========================= */
1386 :
1387 115 : if (some_problems_when_reading > 0)
1388 : {
1389 0 : if (offset_fals < 1 + 32)
1390 0 : pMMBDXP->nFields = 0;
1391 : else
1392 0 : pMMBDXP->nFields =
1393 0 : (MM_EXT_DBF_N_FIELDS)(((offset_fals - 1) - 32) / 32);
1394 : }
1395 : else
1396 : {
1397 : // There's a chance that bytes_acumulats could overflow if it's GUInt32.
1398 : // For that reason it's better to promote to GUInt64.
1399 115 : GUInt64 bytes_acumulats = 1;
1400 :
1401 115 : pMMBDXP->nFields = 0;
1402 :
1403 115 : VSIFSeekL(pf, 0, SEEK_END);
1404 115 : if (32 - 1 < VSIFTellL(pf))
1405 : {
1406 115 : VSIFSeekL(pf, 32, SEEK_SET);
1407 : do
1408 : {
1409 1081 : bytes_per_camp = 0;
1410 1081 : VSIFSeekL(pf,
1411 1081 : 32 + (MM_FILE_OFFSET)pMMBDXP->nFields * 32 +
1412 : (MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF + 1 + 4),
1413 : SEEK_SET);
1414 2162 : if (1 != VSIFReadL(&bytes_per_camp, 1, 1, pf) ||
1415 2162 : 1 != VSIFReadL(&un_byte, 1, 1, pf) ||
1416 1081 : 1 != VSIFReadL(&tretze_bytes, 3 + sizeof(bytes_per_camp), 1,
1417 : pf))
1418 : {
1419 0 : VSIFree(pMMBDXP->pField);
1420 0 : pMMBDXP->pField = nullptr;
1421 0 : pMMBDXP->nFields = 0;
1422 0 : fclose_and_nullify(&pMMBDXP->pfDataBase);
1423 0 : return 1;
1424 : }
1425 1081 : if (bytes_per_camp == 0)
1426 79 : memcpy(&bytes_per_camp, (char *)(&tretze_bytes) + 3,
1427 : sizeof(bytes_per_camp));
1428 :
1429 1081 : bytes_acumulats += bytes_per_camp;
1430 1081 : pMMBDXP->nFields++;
1431 1081 : } while (bytes_acumulats < pMMBDXP->BytesPerRecord);
1432 : }
1433 : }
1434 :
1435 115 : if (pMMBDXP->nFields != 0)
1436 : {
1437 115 : VSIFree(pMMBDXP->pField);
1438 115 : pMMBDXP->pField = MM_CreateAllFields(pMMBDXP->nFields);
1439 115 : if (!pMMBDXP->pField)
1440 : {
1441 0 : pMMBDXP->nFields = 0;
1442 0 : fclose_and_nullify(&pMMBDXP->pfDataBase);
1443 0 : return 1;
1444 : }
1445 : }
1446 : else
1447 : {
1448 0 : VSIFree(pMMBDXP->pField);
1449 0 : pMMBDXP->pField = nullptr;
1450 : }
1451 :
1452 115 : VSIFSeekL(pf, 32, SEEK_SET);
1453 1196 : for (nIField = 0; nIField < pMMBDXP->nFields; nIField++)
1454 : {
1455 1081 : if (1 != VSIFReadL(pMMBDXP->pField[nIField].FieldName,
1456 1081 : MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF, 1, pf) ||
1457 2162 : 1 != VSIFReadL(&(pMMBDXP->pField[nIField].FieldType), 1, 1, pf) ||
1458 2162 : 1 != VSIFReadL(&(pMMBDXP->pField[nIField].reserved_1), 4, 1, pf) ||
1459 1081 : 1 != VSIFReadL(&(pMMBDXP->pField[nIField].BytesPerField), 1, 1,
1460 1081 : pf) ||
1461 1081 : 1 != VSIFReadL(&(pMMBDXP->pField[nIField].DecimalsIfFloat), 1, 1,
1462 1081 : pf) ||
1463 2162 : 1 != VSIFReadL(&(pMMBDXP->pField[nIField].reserved_2), 13, 1, pf) ||
1464 : 1 !=
1465 1081 : VSIFReadL(&(pMMBDXP->pField[nIField].MDX_field_flag), 1, 1, pf))
1466 : {
1467 0 : VSIFree(pMMBDXP->pField);
1468 0 : pMMBDXP->pField = nullptr;
1469 0 : pMMBDXP->nFields = 0;
1470 0 : VSIFCloseL(pf);
1471 0 : pMMBDXP->pfDataBase = nullptr;
1472 0 : return 1;
1473 : }
1474 :
1475 1081 : if (pMMBDXP->pField[nIField].FieldType == 'F')
1476 0 : pMMBDXP->pField[nIField].FieldType = 'N';
1477 :
1478 1081 : pMMBDXP->pField[nIField]
1479 1081 : .FieldName[MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF - 1] = '\0';
1480 1081 : if (EQUAL(pMMBDXP->pField[nIField].FieldName,
1481 : szMMNomCampIdGraficDefecte))
1482 115 : pMMBDXP->IdGraficField = nIField;
1483 :
1484 : // Limit BytesPerField to avoid later integer overflows
1485 : // We could potentially limit further...
1486 1081 : if (pMMBDXP->pField[nIField].BytesPerField > (uint32_t)(INT32_MAX - 1))
1487 : {
1488 0 : VSIFree(pMMBDXP->pField);
1489 0 : pMMBDXP->pField = nullptr;
1490 0 : pMMBDXP->nFields = 0;
1491 0 : VSIFCloseL(pf);
1492 0 : pMMBDXP->pfDataBase = nullptr;
1493 0 : return 1;
1494 : }
1495 :
1496 1081 : if (pMMBDXP->pField[nIField].BytesPerField == 0)
1497 : {
1498 79 : if (!MM_ES_DBF_ESTESA(pMMBDXP->dbf_version))
1499 : {
1500 0 : VSIFree(pMMBDXP->pField);
1501 0 : pMMBDXP->pField = nullptr;
1502 0 : pMMBDXP->nFields = 0;
1503 0 : VSIFCloseL(pf);
1504 0 : pMMBDXP->pfDataBase = nullptr;
1505 0 : return 1;
1506 : }
1507 79 : if (pMMBDXP->pField[nIField].FieldType != 'C')
1508 : {
1509 0 : VSIFree(pMMBDXP->pField);
1510 0 : pMMBDXP->pField = nullptr;
1511 0 : pMMBDXP->nFields = 0;
1512 0 : VSIFCloseL(pf);
1513 0 : pMMBDXP->pfDataBase = nullptr;
1514 0 : return 1;
1515 : }
1516 :
1517 79 : memcpy(&pMMBDXP->pField[nIField].BytesPerField,
1518 79 : (char *)(&pMMBDXP->pField[nIField].reserved_2) + 3,
1519 : sizeof(MM_BYTES_PER_FIELD_TYPE_DBF));
1520 : }
1521 :
1522 1081 : if (nIField)
1523 : {
1524 : // To avoid overflow
1525 966 : if (pMMBDXP->pField[nIField - 1].AccumulatedBytes >
1526 966 : UINT32_MAX - pMMBDXP->pField[nIField - 1].BytesPerField)
1527 : {
1528 0 : VSIFree(pMMBDXP->pField);
1529 0 : pMMBDXP->pField = nullptr;
1530 0 : pMMBDXP->nFields = 0;
1531 0 : VSIFCloseL(pf);
1532 0 : pMMBDXP->pfDataBase = nullptr;
1533 0 : return 1;
1534 : }
1535 :
1536 966 : pMMBDXP->pField[nIField].AccumulatedBytes =
1537 966 : (pMMBDXP->pField[nIField - 1].AccumulatedBytes +
1538 966 : pMMBDXP->pField[nIField - 1].BytesPerField);
1539 : }
1540 : else
1541 : {
1542 115 : pMMBDXP->pField[nIField].AccumulatedBytes = 1;
1543 : }
1544 :
1545 1081 : if (pszRelFile)
1546 : {
1547 : // Usually, in multilingual MiraMon metadata files, the main
1548 : // language is the default one and has no "_cat", "_spa", or
1549 : // "_eng" suffix after the keyword. So, to retrieve all
1550 : // languages in a multilingual file, first, we'll identify
1551 : // the one with no suffix "_cat", "_spa", or "_eng", and then the
1552 : // others. If one of them lacks a value, it gets the default value.
1553 1081 : snprintf(section, sizeof(section), "TAULA_PRINCIPAL:%s",
1554 1081 : pMMBDXP->pField[nIField].FieldName);
1555 :
1556 : // MM_DEF_LANGUAGE
1557 1081 : pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section,
1558 : "descriptor");
1559 1081 : if (pszDesc)
1560 : {
1561 602 : CPLStrlcpy(
1562 602 : pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE],
1563 : pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
1564 :
1565 602 : VSIFree(pszDesc);
1566 : }
1567 : else
1568 479 : *pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE] =
1569 : '\0';
1570 :
1571 : // MM_ENG_LANGUAGE
1572 1081 : pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section,
1573 : "descriptor_eng");
1574 1081 : if (pszDesc)
1575 : {
1576 70 : CPLStrlcpy(
1577 70 : pMMBDXP->pField[nIField].FieldDescription[MM_ENG_LANGUAGE],
1578 : pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
1579 :
1580 70 : if (*pMMBDXP->pField[nIField]
1581 : .FieldDescription[MM_DEF_LANGUAGE] == '\0')
1582 : {
1583 0 : CPLStrlcpy(pMMBDXP->pField[nIField]
1584 0 : .FieldDescription[MM_DEF_LANGUAGE],
1585 : pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
1586 : }
1587 70 : VSIFree(pszDesc);
1588 : }
1589 : else
1590 : {
1591 : // If there is no value descriptor_eng it's because it's the
1592 : // default one. So, it's taken from there.
1593 1011 : CPLStrlcpy(
1594 1011 : pMMBDXP->pField[nIField].FieldDescription[MM_ENG_LANGUAGE],
1595 1011 : pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE],
1596 : MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
1597 : }
1598 :
1599 : // MM_CAT_LANGUAGE
1600 1081 : pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section,
1601 : "descriptor_cat");
1602 1081 : if (pszDesc)
1603 : {
1604 0 : CPLStrlcpy(
1605 0 : pMMBDXP->pField[nIField].FieldDescription[MM_CAT_LANGUAGE],
1606 : pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
1607 :
1608 0 : if (*pMMBDXP->pField[nIField]
1609 : .FieldDescription[MM_DEF_LANGUAGE] == '\0')
1610 : {
1611 0 : CPLStrlcpy(pMMBDXP->pField[nIField]
1612 0 : .FieldDescription[MM_DEF_LANGUAGE],
1613 : pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
1614 : }
1615 :
1616 0 : VSIFree(pszDesc);
1617 : }
1618 : else
1619 : {
1620 : // If there is no value descriptor_cat it's because it's the
1621 : // default one. So, it's taken from there.
1622 1081 : CPLStrlcpy(
1623 1081 : pMMBDXP->pField[nIField].FieldDescription[MM_CAT_LANGUAGE],
1624 1081 : pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE],
1625 : MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
1626 : }
1627 :
1628 : // MM_SPA_LANGUAGE
1629 1081 : pszDesc = MMReturnValueFromSectionINIFile(pszRelFile, section,
1630 : "descriptor_spa");
1631 1081 : if (pszDesc)
1632 : {
1633 70 : CPLStrlcpy(
1634 70 : pMMBDXP->pField[nIField].FieldDescription[MM_SPA_LANGUAGE],
1635 : pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
1636 :
1637 70 : if (*pMMBDXP->pField[nIField]
1638 : .FieldDescription[MM_DEF_LANGUAGE] == '\0')
1639 : {
1640 0 : CPLStrlcpy(pMMBDXP->pField[nIField]
1641 0 : .FieldDescription[MM_DEF_LANGUAGE],
1642 : pszDesc, MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
1643 : }
1644 :
1645 70 : VSIFree(pszDesc);
1646 : }
1647 : else
1648 : {
1649 : // If there is no value descriptor_spa it's because it's the
1650 : // default one. So, it's taken from there.
1651 1011 : CPLStrlcpy(
1652 1011 : pMMBDXP->pField[nIField].FieldDescription[MM_SPA_LANGUAGE],
1653 1011 : pMMBDXP->pField[nIField].FieldDescription[MM_DEF_LANGUAGE],
1654 : MM_MAX_LON_DESCRIPCIO_CAMP_DBF);
1655 : }
1656 : }
1657 : }
1658 :
1659 115 : if (!pMMBDXP->nFields)
1660 : {
1661 0 : if (pMMBDXP->BytesPerRecord)
1662 0 : incoherent_record_size = TRUE;
1663 : }
1664 : else
1665 : {
1666 : // To avoid overflow
1667 115 : if (pMMBDXP->pField[pMMBDXP->nFields - 1].AccumulatedBytes >
1668 115 : UINT32_MAX - pMMBDXP->pField[pMMBDXP->nFields - 1].BytesPerField)
1669 : {
1670 0 : VSIFree(pMMBDXP->pField);
1671 0 : pMMBDXP->pField = nullptr;
1672 0 : pMMBDXP->nFields = 0;
1673 0 : VSIFCloseL(pf);
1674 0 : pMMBDXP->pfDataBase = nullptr;
1675 0 : return 1;
1676 : }
1677 115 : if (pMMBDXP->pField[pMMBDXP->nFields - 1].BytesPerField +
1678 115 : pMMBDXP->pField[pMMBDXP->nFields - 1].AccumulatedBytes >
1679 115 : pMMBDXP->BytesPerRecord)
1680 0 : incoherent_record_size = TRUE;
1681 : }
1682 115 : if (incoherent_record_size)
1683 : {
1684 0 : if (some_problems_when_reading == 0)
1685 : {
1686 0 : incoherent_record_size = FALSE;
1687 0 : VSIFSeekL(pf, offset_reintent, SEEK_SET);
1688 0 : some_problems_when_reading++;
1689 : /* Reset IdGraficField as it might no longer be valid */
1690 0 : pMMBDXP->IdGraficField = 0;
1691 0 : goto reintenta_lectura_per_si_error_CreaCampBD_XP;
1692 : }
1693 : else
1694 : {
1695 0 : VSIFree(pMMBDXP->pField);
1696 0 : pMMBDXP->pField = nullptr;
1697 0 : pMMBDXP->nFields = 0;
1698 0 : VSIFCloseL(pf);
1699 0 : pMMBDXP->pfDataBase = nullptr;
1700 0 : return 1;
1701 : }
1702 : }
1703 :
1704 115 : offset_possible = 32 + 32 * (pMMBDXP->nFields) + 1;
1705 :
1706 115 : if (!incoherent_record_size &&
1707 115 : offset_possible != pMMBDXP->FirstRecordOffset)
1708 : { // Extended names
1709 : MM_FIRST_RECORD_OFFSET_TYPE offset_nom_camp;
1710 : int mida_nom;
1711 :
1712 370 : for (nIField = 0; nIField < pMMBDXP->nFields; nIField++)
1713 : {
1714 : offset_nom_camp =
1715 332 : MM_GiveOffsetExtendedFieldName(pMMBDXP->pField + nIField);
1716 332 : mida_nom = MM_DonaBytesNomEstesCamp(pMMBDXP->pField + nIField);
1717 332 : if (mida_nom > 0 && mida_nom < MM_MAX_LON_FIELD_NAME_DBF &&
1718 101 : offset_nom_camp >= offset_possible &&
1719 101 : offset_nom_camp < pMMBDXP->FirstRecordOffset)
1720 : {
1721 101 : CPLStrlcpy(pMMBDXP->pField[nIField].ClassicalDBFFieldName,
1722 101 : pMMBDXP->pField[nIField].FieldName,
1723 : MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF);
1724 101 : VSIFSeekL(pf, offset_nom_camp, SEEK_SET);
1725 101 : if (1 != VSIFReadL(pMMBDXP->pField[nIField].FieldName, mida_nom,
1726 : 1, pf))
1727 : {
1728 0 : VSIFree(pMMBDXP->pField);
1729 0 : pMMBDXP->pField = nullptr;
1730 0 : pMMBDXP->nFields = 0;
1731 0 : VSIFCloseL(pf);
1732 0 : pMMBDXP->pfDataBase = nullptr;
1733 0 : return 1;
1734 : }
1735 101 : pMMBDXP->pField[nIField].FieldName[mida_nom] = '\0';
1736 :
1737 : // All field names to UTF-8
1738 101 : if (pMMBDXP->CharSet == MM_JOC_CARAC_ANSI_DBASE)
1739 : {
1740 81 : pszString = CPLRecode(pMMBDXP->pField[nIField].FieldName,
1741 : CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
1742 81 : CPLStrlcpy(pMMBDXP->pField[nIField].FieldName, pszString,
1743 : MM_MAX_LON_FIELD_NAME_DBF);
1744 81 : CPLFree(pszString);
1745 : }
1746 20 : else if (pMMBDXP->CharSet == MM_JOC_CARAC_OEM850_DBASE)
1747 : {
1748 15 : MM_oemansi(pMMBDXP->pField[nIField].FieldName);
1749 15 : pszString = CPLRecode(pMMBDXP->pField[nIField].FieldName,
1750 : CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
1751 15 : CPLStrlcpy(pMMBDXP->pField[nIField].FieldName, pszString,
1752 : MM_MAX_LON_FIELD_NAME_DBF - 1);
1753 15 : CPLFree(pszString);
1754 : }
1755 : }
1756 : }
1757 : }
1758 :
1759 115 : pMMBDXP->IdEntityField = MM_MAX_EXT_DBF_N_FIELDS_TYPE;
1760 115 : return 0;
1761 : } // End of MM_ReadExtendedDBFHeaderFromFile()
1762 :
1763 307 : void MM_ReleaseDBFHeader(struct MM_DATA_BASE_XP **data_base_XP)
1764 : {
1765 307 : if (!data_base_XP)
1766 0 : return;
1767 307 : if (!*data_base_XP)
1768 0 : return;
1769 :
1770 307 : MM_ReleaseMainFields(*data_base_XP);
1771 307 : VSIFree(*data_base_XP);
1772 307 : *data_base_XP = nullptr;
1773 :
1774 307 : return;
1775 : }
1776 :
1777 575 : int MM_ModifyFieldNameAndDescriptorIfPresentBD_XP(
1778 : struct MM_FIELD *camp, struct MM_DATA_BASE_XP *bd_xp,
1779 : MM_BOOLEAN no_modifica_descriptor, size_t mida_nom)
1780 : {
1781 : MM_EXT_DBF_N_FIELDS i_camp;
1782 575 : unsigned n_digits_i = 0, i;
1783 575 : int retorn = 0;
1784 :
1785 575 : if (mida_nom == 0)
1786 575 : mida_nom = MM_MAX_LON_FIELD_NAME_DBF;
1787 :
1788 5744 : for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
1789 : {
1790 5239 : if (bd_xp->pField + i_camp == camp)
1791 505 : continue;
1792 4734 : if (!strcasecmp(bd_xp->pField[i_camp].FieldName, camp->FieldName))
1793 70 : break;
1794 : }
1795 575 : if (i_camp < bd_xp->nFields)
1796 : {
1797 70 : retorn = 1;
1798 70 : if (strlen(camp->FieldName) > mida_nom - 2)
1799 0 : camp->FieldName[mida_nom - 2] = '\0';
1800 70 : strcat(camp->FieldName, "0");
1801 70 : for (i = 2; i < (size_t)10; i++)
1802 : {
1803 70 : snprintf(camp->FieldName + strlen(camp->FieldName) - 1,
1804 70 : sizeof(camp->FieldName) - strlen(camp->FieldName) + 1,
1805 : "%u", i);
1806 965 : for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
1807 : {
1808 895 : if (bd_xp->pField + i_camp == camp)
1809 70 : continue;
1810 825 : if (!strcasecmp(bd_xp->pField[i_camp].FieldName,
1811 825 : camp->FieldName))
1812 0 : break;
1813 : }
1814 70 : if (i_camp == bd_xp->nFields)
1815 : {
1816 70 : n_digits_i = 1;
1817 70 : break;
1818 : }
1819 : }
1820 70 : if (i == 10)
1821 : {
1822 0 : camp->FieldName[strlen(camp->FieldName) - 1] = '\0';
1823 0 : if (strlen(camp->FieldName) > mida_nom - 3)
1824 0 : camp->FieldName[mida_nom - 3] = '\0';
1825 0 : strcat(camp->FieldName, "00");
1826 0 : for (i = 10; i < (size_t)100; i++)
1827 : {
1828 0 : snprintf(camp->FieldName + strlen(camp->FieldName) - 2,
1829 0 : sizeof(camp->FieldName) - strlen(camp->FieldName) + 2,
1830 : "%u", i);
1831 0 : for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
1832 : {
1833 0 : if (bd_xp->pField + i_camp == camp)
1834 0 : continue;
1835 0 : if (!strcasecmp(bd_xp->pField[i_camp].FieldName,
1836 0 : camp->FieldName))
1837 0 : break;
1838 : }
1839 0 : if (i_camp == bd_xp->nFields)
1840 : {
1841 0 : n_digits_i = 2;
1842 0 : break;
1843 : }
1844 : }
1845 0 : if (i == 100)
1846 : {
1847 0 : camp->FieldName[strlen(camp->FieldName) - 2] = '\0';
1848 0 : if (strlen(camp->FieldName) > mida_nom - 4)
1849 0 : camp->FieldName[mida_nom - 4] = '\0';
1850 0 : strcat(camp->FieldName, "000");
1851 0 : for (i = 100; i < (size_t)256 + 2; i++)
1852 : {
1853 0 : snprintf(camp->FieldName + strlen(camp->FieldName) - 3,
1854 0 : sizeof(camp->FieldName) - strlen(camp->FieldName) +
1855 : 3,
1856 : "%u", i);
1857 0 : for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
1858 : {
1859 0 : if (bd_xp->pField + i_camp == camp)
1860 0 : continue;
1861 0 : if (!strcasecmp(bd_xp->pField[i_camp].FieldName,
1862 0 : camp->FieldName))
1863 0 : break;
1864 : }
1865 0 : if (i_camp == bd_xp->nFields)
1866 : {
1867 0 : n_digits_i = 3;
1868 0 : break;
1869 : }
1870 : }
1871 0 : if (i == 256)
1872 0 : return 2;
1873 : }
1874 : }
1875 : }
1876 : else
1877 : {
1878 505 : i = 1;
1879 : }
1880 :
1881 575 : if ((*(camp->FieldDescription[0]) == '\0') || no_modifica_descriptor)
1882 476 : return retorn;
1883 :
1884 1329 : for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
1885 : {
1886 1230 : if (bd_xp->pField + i_camp == camp)
1887 99 : continue;
1888 1131 : if (!strcasecmp(bd_xp->pField[i_camp].FieldDescription[0],
1889 1131 : camp->FieldDescription[0]))
1890 0 : break;
1891 : }
1892 99 : if (i_camp == bd_xp->nFields)
1893 99 : return retorn;
1894 :
1895 0 : if (retorn == 1)
1896 : {
1897 0 : if (strlen(camp->FieldDescription[0]) >
1898 0 : MM_MAX_LON_DESCRIPCIO_CAMP_DBF - 4 - n_digits_i)
1899 0 : camp->FieldDescription[0][mida_nom - 4 - n_digits_i] = '\0';
1900 :
1901 0 : snprintf(camp->FieldDescription[0] + strlen(camp->FieldDescription[0]),
1902 : sizeof(camp->FieldDescription[0]) -
1903 0 : strlen(camp->FieldDescription[0]),
1904 : " (%u)", i);
1905 0 : for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
1906 : {
1907 0 : if (bd_xp->pField + i_camp == camp)
1908 0 : continue;
1909 0 : if (!strcasecmp(bd_xp->pField[i_camp].FieldDescription[0],
1910 0 : camp->FieldDescription[0]))
1911 0 : break;
1912 : }
1913 0 : if (i_camp == bd_xp->nFields)
1914 0 : return retorn;
1915 : }
1916 :
1917 0 : retorn = 1;
1918 0 : if (strlen(camp->FieldDescription[0]) >
1919 0 : MM_MAX_LON_DESCRIPCIO_CAMP_DBF - 4 - n_digits_i)
1920 0 : camp->FieldDescription[0][mida_nom - 4 - n_digits_i] = '\0';
1921 0 : camp->FieldDescription[0][strlen(camp->FieldDescription[0]) - 4 -
1922 0 : n_digits_i + 1] = '\0';
1923 0 : if (strlen(camp->FieldDescription[0]) > MM_MAX_LON_DESCRIPCIO_CAMP_DBF - 7)
1924 0 : camp->FieldDescription[0][mida_nom - 7] = '\0';
1925 0 : for (i++; i < (size_t)256; i++)
1926 : {
1927 : //if (camp->FieldDescription[0] + strlen(camp->FieldDescription[0]))
1928 0 : snprintf(camp->FieldDescription[0] + strlen(camp->FieldDescription[0]),
1929 : sizeof(camp->FieldDescription[0]) -
1930 0 : strlen(camp->FieldDescription[0]),
1931 : " (%u)", i);
1932 0 : for (i_camp = 0; i_camp < bd_xp->nFields; i_camp++)
1933 : {
1934 0 : if (bd_xp->pField + i_camp == camp)
1935 0 : continue;
1936 0 : if (!strcasecmp(bd_xp->pField[i_camp].FieldName, camp->FieldName))
1937 0 : break;
1938 : }
1939 0 : if (i_camp == bd_xp->nFields)
1940 0 : return retorn;
1941 : }
1942 0 : return 2;
1943 : } // End of MM_ModifyFieldNameAndDescriptorIfPresentBD_XP()
1944 :
1945 575 : static int MM_DuplicateMultilingualString(
1946 : char *(szChain_final[MM_NUM_IDIOMES_MD_MULTIDIOMA]),
1947 : const char *const(szChain_inicial[MM_NUM_IDIOMES_MD_MULTIDIOMA]))
1948 : {
1949 : size_t i;
1950 :
1951 2875 : for (i = 0; i < MM_NUM_IDIOMES_MD_MULTIDIOMA; i++)
1952 : {
1953 2300 : if (szChain_inicial[i])
1954 : {
1955 0 : if (nullptr == (szChain_final[i] = strdup(szChain_inicial[i])))
1956 0 : return 1;
1957 : }
1958 : else
1959 2300 : szChain_final[i] = nullptr;
1960 : }
1961 575 : return 0;
1962 : }
1963 :
1964 575 : int MM_DuplicateFieldDBXP(struct MM_FIELD *camp_final,
1965 : const struct MM_FIELD *camp_inicial)
1966 : {
1967 575 : *camp_final = *camp_inicial;
1968 :
1969 575 : if (0 != MM_DuplicateMultilingualString(
1970 575 : camp_final->Separator,
1971 575 : (const char *const(*))camp_inicial->Separator))
1972 0 : return 1;
1973 :
1974 575 : return 0;
1975 : }
1976 :
1977 : // If n_bytes==SIZE_MAX, the parameter is ignored ant, then,
1978 : // it's assumed that szszChain is NUL terminated
1979 2619 : char *MM_oemansi_n(char *szszChain, size_t n_bytes)
1980 : {
1981 : size_t u_i;
1982 : unsigned char *punter_bait;
1983 2619 : unsigned char t_oemansi[128] = {
1984 : 199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232, 239, 238,
1985 : 236, 196, 197, 201, 230, 198, 244, 246, 242, 251, 249, 255, 214,
1986 : 220, 248, 163, 216, 215, 131, 225, 237, 243, 250, 241, 209, 170,
1987 : 186, 191, 174, 172, 189, 188, 161, 171, 187, 164, 164, 164, 166,
1988 : 166, 193, 194, 192, 169, 166, 166, 164, 164, 162, 165, 164, 164,
1989 : 164, 164, 164, 164, 164, 227, 195, 164, 164, 164, 164, 166, 164,
1990 : 164, 164, 240, 208, 202, 203, 200, 180, 205, 206, 207, 164, 164,
1991 : 164, 164, 166, 204, 164, 211, 223, 212, 210, 245, 213, 181, 254,
1992 : 222, 218, 219, 217, 253, 221, 175, 180, 173, 177, 164, 190, 182,
1993 : 167, 247, 184, 176, 168, 183, 185, 179, 178, 164, 183};
1994 2619 : if (n_bytes == SIZE_MAX)
1995 : {
1996 26979 : for (punter_bait = (unsigned char *)szszChain; *punter_bait;
1997 24504 : punter_bait++)
1998 : {
1999 24504 : if (*punter_bait > 127)
2000 299 : *punter_bait = t_oemansi[*punter_bait - 128];
2001 : }
2002 : }
2003 : else
2004 : {
2005 2004 : for (u_i = 0, punter_bait = (unsigned char *)szszChain; u_i < n_bytes;
2006 1860 : punter_bait++, u_i++)
2007 : {
2008 1860 : if (*punter_bait > 127)
2009 0 : *punter_bait = t_oemansi[*punter_bait - 128];
2010 : }
2011 : }
2012 2619 : return szszChain;
2013 : }
2014 :
2015 : // An implementation of non-sensitive strstr()
2016 1250 : char *MM_stristr(const char *haystack, const char *needle)
2017 : {
2018 1250 : if (!haystack)
2019 0 : return nullptr;
2020 :
2021 1250 : if (!needle)
2022 0 : return nullptr;
2023 :
2024 1250 : if (!*needle)
2025 0 : return (char *)haystack;
2026 :
2027 1250 : char *p1 = (char *)haystack;
2028 27229 : while (*p1 != '\0' && !EQUALN(p1, needle, strlen(needle)))
2029 25979 : p1++;
2030 :
2031 1250 : if (*p1 == '\0')
2032 494 : return nullptr;
2033 :
2034 756 : return p1;
2035 : }
2036 :
2037 2475 : char *MM_oemansi(char *szszChain)
2038 : {
2039 2475 : return MM_oemansi_n(szszChain, SIZE_MAX);
2040 : }
2041 :
2042 651 : static MM_BOOLEAN MM_FillFieldDB_XP(
2043 : struct MM_FIELD *camp, const char *FieldName,
2044 : const char *FieldDescriptionEng, const char *FieldDescriptionCat,
2045 : const char *FieldDescriptionSpa, char FieldType,
2046 : MM_BYTES_PER_FIELD_TYPE_DBF BytesPerField, MM_BYTE DecimalsIfFloat)
2047 : {
2048 : char nom_temp[MM_MAX_LON_FIELD_NAME_DBF];
2049 : int retorn_valida_nom_camp;
2050 :
2051 651 : if (FieldName)
2052 : {
2053 651 : retorn_valida_nom_camp = MM_ISExtendedNameBD_XP(FieldName);
2054 651 : if (retorn_valida_nom_camp == MM_DBF_NAME_NO_VALID)
2055 0 : return FALSE;
2056 651 : CPLStrlcpy(camp->FieldName, FieldName, MM_MAX_LON_FIELD_NAME_DBF);
2057 :
2058 651 : if (retorn_valida_nom_camp == MM_VALID_EXTENDED_DBF_NAME)
2059 : {
2060 0 : MM_CalculateBytesExtendedFieldName(camp);
2061 0 : CPLStrlcpy(nom_temp, FieldName, MM_MAX_LON_FIELD_NAME_DBF);
2062 0 : MM_ReturnValidClassicDBFFieldName(nom_temp);
2063 0 : nom_temp[MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF] = '\0';
2064 0 : CPLStrlcpy(camp->ClassicalDBFFieldName, nom_temp,
2065 : MM_MAX_LON_CLASSICAL_FIELD_NAME_DBF);
2066 : }
2067 : }
2068 :
2069 651 : if (FieldDescriptionEng)
2070 651 : CPLStrlcpy(camp->FieldDescription[MM_DEF_LANGUAGE], FieldDescriptionEng,
2071 : sizeof(camp->FieldDescription[MM_DEF_LANGUAGE]));
2072 : else
2073 0 : strcpy(camp->FieldDescription[MM_DEF_LANGUAGE], "\0");
2074 :
2075 651 : if (FieldDescriptionEng)
2076 651 : CPLStrlcpy(camp->FieldDescription[MM_ENG_LANGUAGE], FieldDescriptionEng,
2077 : sizeof(camp->FieldDescription[MM_ENG_LANGUAGE]));
2078 : else
2079 0 : strcpy(camp->FieldDescription[MM_ENG_LANGUAGE], "\0");
2080 :
2081 651 : if (FieldDescriptionCat)
2082 651 : CPLStrlcpy(camp->FieldDescription[MM_CAT_LANGUAGE], FieldDescriptionCat,
2083 : sizeof(camp->FieldDescription[MM_CAT_LANGUAGE]));
2084 : else
2085 0 : strcpy(camp->FieldDescription[MM_CAT_LANGUAGE], "\0");
2086 :
2087 651 : if (FieldDescriptionSpa)
2088 651 : CPLStrlcpy(camp->FieldDescription[MM_SPA_LANGUAGE], FieldDescriptionSpa,
2089 : sizeof(camp->FieldDescription[MM_SPA_LANGUAGE]));
2090 : else
2091 0 : strcpy(camp->FieldDescription[MM_SPA_LANGUAGE], "\0");
2092 :
2093 651 : camp->FieldType = FieldType;
2094 651 : camp->DecimalsIfFloat = DecimalsIfFloat;
2095 651 : camp->BytesPerField = BytesPerField;
2096 651 : return TRUE;
2097 : }
2098 :
2099 27 : size_t MM_DefineFirstPolygonFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp,
2100 : MM_BYTE n_perimeter_decimals,
2101 : MM_BYTE n_area_decimals_decimals)
2102 : {
2103 27 : MM_EXT_DBF_N_FIELDS i_camp = 0;
2104 :
2105 27 : MM_FillFieldDB_XP(
2106 27 : bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte,
2107 : szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat,
2108 : szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0);
2109 27 : bd_xp->IdGraficField = 0;
2110 27 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC;
2111 27 : i_camp++;
2112 :
2113 27 : MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNVertexsDefecte,
2114 : szNumberOfVerticesEng, szNumberOfVerticesCat,
2115 : szNumberOfVerticesSpa, 'N', MM_MIN_WIDTH_N_VERTEXS, 0);
2116 27 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_VERTEXS;
2117 27 : i_camp++;
2118 :
2119 27 : MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampPerimetreDefecte,
2120 : szPerimeterOfThePolygonEng, szPerimeterOfThePolygonCat,
2121 : szPerimeterOfThePolygonSpa, 'N', MM_MIN_WIDTH_LONG,
2122 : n_perimeter_decimals);
2123 27 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_PERIMETRE;
2124 27 : i_camp++;
2125 :
2126 27 : MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampAreaDefecte,
2127 : szAreaOfThePolygonEng, szAreaOfThePolygonCat,
2128 : szAreaOfThePolygonSpa, 'N', MM_MIN_WIDTH_AREA,
2129 : n_area_decimals_decimals);
2130 27 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_AREA;
2131 27 : i_camp++;
2132 :
2133 27 : MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNArcsDefecte,
2134 : szNumberOfArcsEng, szNumberOfArcsCat, szNumberOfArcsSpa,
2135 : 'N', MM_MIN_WIDTH_N_ARCS, 0);
2136 27 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_ARCS;
2137 27 : i_camp++;
2138 :
2139 27 : MM_FillFieldDB_XP(
2140 27 : bd_xp->pField + i_camp, szMMNomCampNPoligonsDefecte,
2141 : szNumberOfElementaryPolygonsEng, szNumberOfElementaryPolygonsCat,
2142 : szNumberOfElementaryPolygonsSpa, 'N', MM_MIN_WIDTH_N_POLIG, 0);
2143 27 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_POLIG;
2144 27 : i_camp++;
2145 :
2146 27 : return i_camp;
2147 : }
2148 :
2149 57 : size_t MM_DefineFirstArcFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp,
2150 : MM_BYTE n_decimals)
2151 : {
2152 : MM_EXT_DBF_N_FIELDS i_camp;
2153 :
2154 57 : i_camp = 0;
2155 57 : MM_FillFieldDB_XP(
2156 57 : bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte,
2157 : szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat,
2158 : szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0);
2159 57 : bd_xp->IdGraficField = 0;
2160 57 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC;
2161 57 : i_camp++;
2162 :
2163 57 : MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNVertexsDefecte,
2164 : szNumberOfVerticesEng, szNumberOfVerticesCat,
2165 : szNumberOfVerticesSpa, 'N', MM_MIN_WIDTH_N_VERTEXS, 0);
2166 57 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_N_VERTEXS;
2167 57 : i_camp++;
2168 :
2169 57 : MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampLongitudArcDefecte,
2170 : szLengthOfAarcEng, szLengthOfAarcCat, szLengthOfAarcSpa,
2171 : 'N', MM_MIN_WIDTH_LONG, n_decimals);
2172 57 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_LONG_ARC;
2173 57 : i_camp++;
2174 :
2175 57 : MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNodeIniDefecte,
2176 : szInitialNodeEng, szInitialNodeCat, szInitialNodeSpa, 'N',
2177 : MM_MIN_WIDTH_INITIAL_NODE, 0);
2178 57 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_NODE_INI;
2179 57 : i_camp++;
2180 :
2181 57 : MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampNodeFiDefecte,
2182 : szFinalNodeEng, szFinalNodeCat, szFinalNodeSpa, 'N',
2183 : MM_MIN_WIDTH_FINAL_NODE, 0);
2184 57 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_NODE_FI;
2185 57 : i_camp++;
2186 :
2187 57 : return i_camp;
2188 : }
2189 :
2190 57 : size_t MM_DefineFirstNodeFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp)
2191 : {
2192 : MM_EXT_DBF_N_FIELDS i_camp;
2193 :
2194 57 : i_camp = 0;
2195 :
2196 57 : MM_FillFieldDB_XP(
2197 57 : bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte,
2198 : szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat,
2199 : szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0);
2200 57 : bd_xp->IdGraficField = 0;
2201 57 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC;
2202 57 : i_camp++;
2203 :
2204 57 : MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampArcsANodeDefecte,
2205 : szNumberOfArcsToNodeEng, szNumberOfArcsToNodeCat,
2206 : szNumberOfArcsToNodeSpa, 'N', MM_MIN_WIDTH_ARCS_TO_NODE,
2207 : 0);
2208 57 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ARCS_A_NOD;
2209 57 : i_camp++;
2210 :
2211 57 : MM_FillFieldDB_XP(bd_xp->pField + i_camp, szMMNomCampTipusNodeDefecte,
2212 : szNodeTypeEng, szNodeTypeCat, szNodeTypeSpa, 'N', 1, 0);
2213 57 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_TIPUS_NODE;
2214 57 : i_camp++;
2215 :
2216 57 : return i_camp;
2217 : }
2218 :
2219 33 : size_t MM_DefineFirstPointFieldsDB_XP(struct MM_DATA_BASE_XP *bd_xp)
2220 : {
2221 33 : size_t i_camp = 0;
2222 :
2223 33 : MM_FillFieldDB_XP(
2224 33 : bd_xp->pField + i_camp, szMMNomCampIdGraficDefecte,
2225 : szInternalGraphicIdentifierEng, szInternalGraphicIdentifierCat,
2226 : szInternalGraphicIdentifierSpa, 'N', MM_MIN_WIDTH_ID_GRAFIC, 0);
2227 33 : bd_xp->IdGraficField = 0;
2228 33 : (bd_xp->pField + i_camp)->GeoTopoTypeField = (MM_BYTE)MM_CAMP_ES_ID_GRAFIC;
2229 33 : i_camp++;
2230 :
2231 33 : return i_camp;
2232 : }
2233 :
2234 : /*
2235 : Controlling the number of significant figures is often crucial in science
2236 : and technology, and the best option when nothing is known about the number
2237 : to be printed (if it is really small (near to 0), or very large), and
2238 : allows a good return (the same value) into memory when re-read from a text
2239 : file with scanf() functions.
2240 : If you need to print 0.00000000000000000000000000000000000000001 with %f
2241 : you will need an extremely large string. If you print 1980.45 with %E you
2242 : obtain 1.98045E+003, needing more space, and not being easy to interpret
2243 : for some people. Moreover, “normal” users do not want to see 1.0 as
2244 : 1.0E+000 or 1.0E+00. The choice of the format specifier, and the integer
2245 : to be passed to the ‘*’ is not always easy,
2246 : and MM_SprintfDoubleSignifFigures() automatically uses a “fair” notation
2247 : whenever it is possible, resulting in shorter strings, being them under
2248 : control (the maximum length of the resulting string is always known).
2249 : Moreover, it avoids some failures in compilers not expecting
2250 : NAN or INF values.
2251 : */
2252 233 : int MM_SprintfDoubleSignifFigures(char *szChain, size_t size_szChain,
2253 : int nSignifFigures, double dfRealValue)
2254 : {
2255 : double VALOR_LIMIT_PRINT_IN_FORMAT_E;
2256 : double VALOR_TOO_SMALL_TO_PRINT_f;
2257 : int retorn, exponent;
2258 : char *ptr;
2259 :
2260 : #define N_POWERS MM_MAX_XS_DOUBLE
2261 :
2262 : /* This expression ensures that no garbage is written in
2263 : the non-significant digits of the integer part, i.e., requesting 9E20
2264 : with 16 significant digits does not print 90000000000000004905, where
2265 : "4905" is garbage generated by the print call with such a large value
2266 : and "%.16f", but rather writes 9.000000000000000E+20.
2267 : At the same time, it ensures that 9000 requested with 4 significant
2268 : digits is written as 9000 and that requested with 5 significant digits
2269 : is written as 9000.0, but that requested with 3 significant digits is
2270 : written as 9.00E+03. */
2271 233 : double potencies_de_10[N_POWERS] = {
2272 : 1E+1, 1E+2, 1E+3, 1E+4, 1E+5, 1E+6, 1E+7, 1E+8, 1E+9,
2273 : 1E+10, 1E+11, 1E+12, 1E+13, 1E+14, 1E+15, 1E+16, 1E+17};
2274 :
2275 : /* This expression ensures that -9E-7 requested with 11 significant digits
2276 : still uses "natural" notation and gives -0.0000009000000000, which still
2277 : fits exactly within the 20 characters of a 'N' field in dBASE, while
2278 : requested with 12 significant digits jumps to exponential notation and
2279 : writes -9.00000000000E-07, which also fits (in this case, comfortably)
2280 : within the 20 characters of dBASE.
2281 : The expression could be replaced by: pow(10,-max(0,20-2-signif_digits)); */
2282 233 : double fraccions_de_10[N_POWERS + 1] = {
2283 : 1E-1, 1E-2, 1E-3, 1E-4, 1E-5, 1E-6, 1E-7, 1E-8, 1E-9,
2284 : 1E-10, 1E-11, 1E-12, 1E-13, 1E-14, 1E-15, 1E-16, 1E-17, 1E-18};
2285 :
2286 233 : if (!szChain)
2287 0 : return 0;
2288 :
2289 233 : if (size_szChain < 3)
2290 0 : return 0;
2291 :
2292 233 : memset(szChain, '\0', size_szChain);
2293 :
2294 233 : if (MM_IsNANDouble(dfRealValue))
2295 0 : return snprintf(szChain, size_szChain, "NAN");
2296 :
2297 233 : if (MM_IsDoubleInfinite(dfRealValue))
2298 0 : return snprintf(szChain, size_szChain, "INF");
2299 :
2300 233 : if (dfRealValue == 0.0)
2301 3 : return snprintf(szChain, size_szChain, "%.*f", nSignifFigures, 0.0);
2302 :
2303 230 : if (nSignifFigures < 1)
2304 0 : return snprintf(szChain, size_szChain, "0.0");
2305 :
2306 230 : if (nSignifFigures > N_POWERS)
2307 0 : nSignifFigures = N_POWERS;
2308 :
2309 230 : retorn = snprintf(szChain, size_szChain, "%.*E", nSignifFigures - 1,
2310 : dfRealValue);
2311 :
2312 230 : VALOR_LIMIT_PRINT_IN_FORMAT_E = potencies_de_10[nSignifFigures - 1];
2313 230 : VALOR_TOO_SMALL_TO_PRINT_f =
2314 230 : fraccions_de_10[MM_MAX_XS_DOUBLE - nSignifFigures];
2315 :
2316 230 : if (dfRealValue > VALOR_LIMIT_PRINT_IN_FORMAT_E ||
2317 212 : dfRealValue < -VALOR_LIMIT_PRINT_IN_FORMAT_E ||
2318 1 : (dfRealValue < VALOR_TOO_SMALL_TO_PRINT_f &&
2319 1 : dfRealValue > -VALOR_TOO_SMALL_TO_PRINT_f))
2320 18 : return retorn;
2321 :
2322 212 : ptr = strchr(szChain, 'E');
2323 212 : if (!ptr)
2324 0 : return 0;
2325 212 : exponent = atoi(ptr + 1);
2326 :
2327 212 : return sprintf(szChain, "%.*f",
2328 212 : (nSignifFigures - exponent - 1) > 0
2329 : ? (nSignifFigures - exponent - 1)
2330 : : 0,
2331 : dfRealValue);
2332 : #undef N_POWERS
2333 : } // End of SprintfDoubleXifSignif()
2334 :
2335 1331 : int MM_SecureCopyStringFieldValue(char **pszStringDst, const char *pszStringSrc,
2336 : MM_EXT_DBF_N_FIELDS *nStringCurrentLength)
2337 : {
2338 :
2339 1331 : if (!pszStringSrc)
2340 : {
2341 0 : if (1 >= *nStringCurrentLength)
2342 : {
2343 0 : void *new_ptr = VSIRealloc(*pszStringDst, 2);
2344 0 : if (!new_ptr)
2345 0 : return 1;
2346 0 : *pszStringDst = new_ptr;
2347 0 : *nStringCurrentLength = (MM_EXT_DBF_N_FIELDS)2;
2348 : }
2349 0 : strcpy(*pszStringDst, "\0");
2350 0 : return 0;
2351 : }
2352 :
2353 1331 : if (strlen(pszStringSrc) >= *nStringCurrentLength)
2354 : {
2355 450 : void *new_ptr = VSIRealloc(*pszStringDst, strlen(pszStringSrc) + 1);
2356 450 : if (!new_ptr)
2357 0 : return 1;
2358 450 : (*pszStringDst) = new_ptr;
2359 450 : *nStringCurrentLength = (MM_EXT_DBF_N_FIELDS)(strlen(pszStringSrc) + 1);
2360 : }
2361 1331 : strcpy(*pszStringDst, pszStringSrc);
2362 1331 : return 0;
2363 : }
2364 :
2365 : // This function assumes that all the file is saved in disk and closed.
2366 117 : int MM_ChangeDBFWidthField(struct MM_DATA_BASE_XP *data_base_XP,
2367 : MM_EXT_DBF_N_FIELDS nIField,
2368 : MM_BYTES_PER_FIELD_TYPE_DBF nNewWidth,
2369 : MM_BYTE nNewPrecision)
2370 : {
2371 117 : char *record, *whites = nullptr;
2372 : MM_BYTES_PER_FIELD_TYPE_DBF l_glop1, l_glop2, i_glop2;
2373 : MM_EXT_DBF_N_RECORDS nfitx, i_reg;
2374 : int canvi_amplada; // change width
2375 : GInt32 j;
2376 : MM_EXT_DBF_N_FIELDS i_camp;
2377 : size_t retorn_fwrite;
2378 : int retorn_TruncaFitxer;
2379 :
2380 117 : if (!data_base_XP)
2381 0 : return 1;
2382 :
2383 117 : canvi_amplada = nNewWidth - data_base_XP->pField[nIField].BytesPerField;
2384 :
2385 117 : if (data_base_XP->nRecords != 0)
2386 : {
2387 48 : l_glop1 = data_base_XP->pField[nIField].AccumulatedBytes;
2388 48 : i_glop2 = l_glop1 + data_base_XP->pField[nIField].BytesPerField;
2389 48 : if (nIField == data_base_XP->nFields - 1)
2390 26 : l_glop2 = 0;
2391 : else
2392 22 : l_glop2 = data_base_XP->BytesPerRecord -
2393 22 : data_base_XP->pField[nIField + 1].AccumulatedBytes;
2394 :
2395 48 : if ((record = VSICalloc(1, (size_t)data_base_XP->BytesPerRecord)) ==
2396 : nullptr)
2397 0 : return 1;
2398 :
2399 48 : record[data_base_XP->BytesPerRecord - 1] = MM_SetEndOfString;
2400 :
2401 48 : if ((whites = (char *)VSICalloc(1, (size_t)nNewWidth)) == nullptr)
2402 : {
2403 0 : VSIFree(record);
2404 0 : return 1;
2405 : }
2406 48 : memset(whites, ' ', nNewWidth);
2407 :
2408 48 : nfitx = data_base_XP->nRecords;
2409 48 : i_reg = (canvi_amplada < 0 ? 0 : nfitx - 1);
2410 : while (TRUE)
2411 : {
2412 48 : if (0 != VSIFSeekL(data_base_XP->pfDataBase,
2413 48 : data_base_XP->FirstRecordOffset +
2414 48 : (MM_FILE_OFFSET)i_reg *
2415 48 : data_base_XP->BytesPerRecord,
2416 : SEEK_SET))
2417 : {
2418 0 : VSIFree(whites);
2419 0 : VSIFree(record);
2420 0 : return 1;
2421 : }
2422 :
2423 48 : if (1 != VSIFReadL(record, data_base_XP->BytesPerRecord, 1,
2424 : data_base_XP->pfDataBase))
2425 : {
2426 0 : VSIFree(whites);
2427 0 : VSIFree(record);
2428 0 : return 1;
2429 : }
2430 :
2431 48 : if (0 !=
2432 48 : VSIFSeekL(
2433 : data_base_XP->pfDataBase,
2434 48 : (MM_FILE_OFFSET)data_base_XP->FirstRecordOffset +
2435 48 : i_reg * ((MM_FILE_OFFSET)data_base_XP->BytesPerRecord +
2436 : canvi_amplada),
2437 : SEEK_SET))
2438 : {
2439 0 : VSIFree(whites);
2440 0 : VSIFree(record);
2441 0 : return 1;
2442 : }
2443 :
2444 48 : if (1 != VSIFWriteL(record, l_glop1, 1, data_base_XP->pfDataBase))
2445 : {
2446 0 : VSIFree(whites);
2447 0 : VSIFree(record);
2448 0 : return 1;
2449 : }
2450 :
2451 48 : switch (data_base_XP->pField[nIField].FieldType)
2452 : {
2453 30 : case 'C':
2454 : case 'L':
2455 30 : memcpy(whites, record + l_glop1,
2456 : (canvi_amplada < 0
2457 : ? nNewWidth
2458 30 : : data_base_XP->pField[nIField].BytesPerField));
2459 30 : retorn_fwrite = VSIFWriteL(whites, nNewWidth, 1,
2460 : data_base_XP->pfDataBase);
2461 :
2462 30 : if (1 != retorn_fwrite)
2463 : {
2464 0 : VSIFree(whites);
2465 0 : VSIFree(record);
2466 0 : return 1;
2467 : }
2468 30 : break;
2469 18 : case 'N':
2470 :
2471 18 : if (canvi_amplada >= 0)
2472 : {
2473 18 : if (1 != VSIFWriteL(whites, canvi_amplada, 1,
2474 18 : data_base_XP->pfDataBase) ||
2475 : 1 !=
2476 18 : VSIFWriteL(
2477 18 : record + l_glop1,
2478 18 : data_base_XP->pField[nIField].BytesPerField,
2479 : 1, data_base_XP->pfDataBase))
2480 : {
2481 0 : VSIFree(whites);
2482 0 : VSIFree(record);
2483 0 : return 1;
2484 : }
2485 : }
2486 0 : else if (canvi_amplada < 0)
2487 : {
2488 0 : j = (GInt32)(l_glop1 + (data_base_XP->pField[nIField]
2489 0 : .BytesPerField -
2490 : 1));
2491 : while (TRUE)
2492 : {
2493 0 : j--;
2494 :
2495 0 : if (j < (GInt32)l_glop1 || record[j] == ' ')
2496 : {
2497 0 : j++;
2498 0 : break;
2499 : }
2500 : }
2501 :
2502 0 : if ((data_base_XP->pField[nIField].BytesPerField +
2503 0 : l_glop1 - j) < nNewWidth)
2504 0 : j -= (GInt32)(nNewWidth -
2505 0 : (data_base_XP->pField[nIField]
2506 0 : .BytesPerField +
2507 : l_glop1 - j));
2508 :
2509 0 : retorn_fwrite = VSIFWriteL(record + j, nNewWidth, 1,
2510 : data_base_XP->pfDataBase);
2511 0 : if (1 != retorn_fwrite)
2512 : {
2513 0 : VSIFree(whites);
2514 0 : VSIFree(record);
2515 0 : return 1;
2516 : }
2517 : }
2518 :
2519 18 : break;
2520 0 : default:
2521 0 : VSIFree(whites);
2522 0 : VSIFree(record);
2523 0 : return 1;
2524 : }
2525 48 : if (l_glop2)
2526 : {
2527 22 : retorn_fwrite = VSIFWriteL(record + i_glop2, l_glop2, 1,
2528 : data_base_XP->pfDataBase);
2529 22 : if (1 != retorn_fwrite)
2530 : {
2531 0 : VSIFree(whites);
2532 0 : VSIFree(record);
2533 0 : return 1;
2534 : }
2535 : }
2536 :
2537 48 : if (canvi_amplada < 0)
2538 : {
2539 0 : if (i_reg + 1 == nfitx)
2540 0 : break;
2541 0 : i_reg++;
2542 : }
2543 : else
2544 : {
2545 48 : if (i_reg == 0)
2546 48 : break;
2547 0 : i_reg--;
2548 : }
2549 : }
2550 :
2551 48 : VSIFree(whites);
2552 48 : VSIFree(record);
2553 :
2554 48 : retorn_TruncaFitxer = VSIFTruncateL(
2555 : data_base_XP->pfDataBase,
2556 48 : (MM_FILE_OFFSET)data_base_XP->FirstRecordOffset +
2557 48 : (MM_FILE_OFFSET)data_base_XP->nRecords *
2558 48 : ((MM_FILE_OFFSET)data_base_XP->BytesPerRecord +
2559 : canvi_amplada));
2560 48 : if (canvi_amplada < 0 && retorn_TruncaFitxer)
2561 0 : return 1;
2562 : } /* Fi de registres de != 0*/
2563 :
2564 117 : if (canvi_amplada != 0)
2565 : {
2566 117 : data_base_XP->pField[nIField].BytesPerField = nNewWidth;
2567 117 : data_base_XP->BytesPerRecord += canvi_amplada;
2568 117 : for (i_camp = (MM_EXT_DBF_N_FIELDS)(nIField + 1);
2569 477 : i_camp < data_base_XP->nFields; i_camp++)
2570 360 : data_base_XP->pField[i_camp].AccumulatedBytes += canvi_amplada;
2571 : }
2572 117 : data_base_XP->pField[nIField].DecimalsIfFloat = nNewPrecision;
2573 :
2574 117 : if ((MM_OpenIfNeededAndUpdateEntireHeader(data_base_XP)) == FALSE)
2575 0 : return 1;
2576 :
2577 117 : return 0;
2578 : } /* End of MMChangeCFieldWidthDBF() */
2579 :
2580 1525 : static void MM_AdoptHeight(double *desti, const double *proposta, uint32_t flag)
2581 : {
2582 1525 : if (*proposta == MM_NODATA_COORD_Z)
2583 0 : return;
2584 :
2585 1525 : if (flag & MM_STRING_HIGHEST_ALTITUDE)
2586 : {
2587 0 : if (*desti == MM_NODATA_COORD_Z || *desti < *proposta)
2588 0 : *desti = *proposta;
2589 : }
2590 1525 : else if (flag & MM_STRING_LOWEST_ALTITUDE)
2591 : {
2592 0 : if (*desti == MM_NODATA_COORD_Z || *desti > *proposta)
2593 0 : *desti = *proposta;
2594 : }
2595 : else
2596 : {
2597 : // First coordinate of this vertice
2598 1525 : if (*desti == MM_NODATA_COORD_Z)
2599 1525 : *desti = *proposta;
2600 : }
2601 : }
2602 :
2603 665 : int MM_GetArcHeights(double *coord_z, VSILFILE *pF, MM_N_VERTICES_TYPE n_vrt,
2604 : struct MM_ZD *pZDescription, uint32_t flag)
2605 : {
2606 : MM_N_HEIGHT_TYPE i;
2607 : MM_N_VERTICES_TYPE i_vrt;
2608 : double *pcoord_z;
2609 : MM_N_HEIGHT_TYPE n_alcada, n_h_total;
2610 : int tipus;
2611 665 : double *alcada = nullptr, *palcada, *palcada_i;
2612 : #define MM_N_ALCADA_LOCAL 50 // Nr of local heights
2613 : double local_CinquantaAlcades[MM_N_ALCADA_LOCAL];
2614 :
2615 2192 : for (i_vrt = 0; i_vrt < n_vrt; i_vrt++)
2616 1527 : coord_z[i_vrt] = MM_NODATA_COORD_Z;
2617 :
2618 665 : if (pZDescription->nZCount == INT_MIN)
2619 0 : return 0;
2620 665 : tipus = MM_ARC_HEIGHT_TYPE(pZDescription->nZCount);
2621 665 : n_alcada = MM_ARC_N_HEIGHTS(pZDescription->nZCount);
2622 665 : if (n_vrt == 0 || n_alcada == 0)
2623 0 : return 0;
2624 :
2625 665 : if (tipus == MM_ARC_HEIGHT_FOR_EACH_VERTEX)
2626 : {
2627 664 : if (n_vrt > (unsigned)(INT_MAX / n_alcada))
2628 : {
2629 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "Integer overflow");
2630 0 : return 1;
2631 : }
2632 664 : n_h_total = (MM_N_HEIGHT_TYPE)n_vrt * n_alcada;
2633 : }
2634 : else
2635 1 : n_h_total = n_alcada;
2636 :
2637 665 : if (n_h_total <= MM_N_ALCADA_LOCAL)
2638 665 : palcada = local_CinquantaAlcades;
2639 : else
2640 : {
2641 0 : if (MMCheckSize_t(n_h_total, sizeof(double)))
2642 0 : return 1;
2643 0 : if (nullptr ==
2644 0 : (palcada = alcada = VSICalloc((size_t)n_h_total, sizeof(double))))
2645 0 : return 1;
2646 : }
2647 :
2648 665 : if (VSIFSeekL(pF, pZDescription->nOffsetZ, SEEK_SET))
2649 : {
2650 0 : if (alcada)
2651 0 : VSIFree(alcada);
2652 0 : return 1;
2653 : }
2654 665 : if (n_h_total !=
2655 665 : (MM_N_HEIGHT_TYPE)VSIFReadL(palcada, sizeof(double), n_h_total, pF))
2656 : {
2657 0 : if (alcada)
2658 0 : VSIFree(alcada);
2659 0 : return 1;
2660 : }
2661 :
2662 665 : if (tipus == MM_ARC_HEIGHT_FOR_EACH_VERTEX)
2663 : {
2664 664 : palcada_i = palcada;
2665 1328 : for (i = 0; i < n_alcada; i++)
2666 : {
2667 2188 : for (i_vrt = 0, pcoord_z = coord_z; i_vrt < n_vrt;
2668 1524 : i_vrt++, pcoord_z++, palcada_i++)
2669 1524 : MM_AdoptHeight(pcoord_z, palcada_i, flag);
2670 : }
2671 : }
2672 : else
2673 : {
2674 1 : palcada_i = palcada;
2675 1 : pcoord_z = coord_z;
2676 2 : for (i = 0; i < n_alcada; i++, palcada_i++)
2677 1 : MM_AdoptHeight(pcoord_z, palcada_i, flag);
2678 :
2679 1 : if (*pcoord_z != MM_NODATA_COORD_Z)
2680 : {
2681 : /*Copio el mateix valor a totes les alcades.*/
2682 3 : for (i_vrt = 1, pcoord_z++; i_vrt < (size_t)n_vrt;
2683 2 : i_vrt++, pcoord_z++)
2684 2 : *pcoord_z = *coord_z;
2685 : }
2686 : }
2687 665 : if (alcada)
2688 0 : VSIFree(alcada);
2689 665 : return 0;
2690 : } // End of MM_GetArcHeights()
2691 :
2692 15322 : static char *MM_l_RemoveWhitespacesFromEndOfString(char *punter,
2693 : size_t l_szChain)
2694 : {
2695 15322 : size_t longitud_szChain = l_szChain;
2696 34628 : while (longitud_szChain > 0)
2697 : {
2698 34216 : longitud_szChain--;
2699 34216 : if (punter[longitud_szChain] != ' ' && punter[longitud_szChain] != '\t')
2700 : {
2701 14910 : break;
2702 : }
2703 19306 : punter[longitud_szChain] = '\0';
2704 : }
2705 15322 : return punter;
2706 : }
2707 :
2708 50 : char *MM_RemoveInitial_and_FinalQuotationMarks(char *szChain)
2709 : {
2710 : char *ptr1, *ptr2;
2711 50 : char cometa = '"';
2712 :
2713 50 : if (*szChain == cometa)
2714 : {
2715 11 : ptr1 = szChain;
2716 11 : ptr2 = ptr1 + 1;
2717 11 : if (*ptr2)
2718 : {
2719 182 : while (*ptr2)
2720 : {
2721 171 : *ptr1 = *ptr2;
2722 171 : ptr1++;
2723 171 : ptr2++;
2724 : }
2725 11 : if (*ptr1 == cometa)
2726 11 : *(ptr1 - 1) = 0;
2727 : else
2728 0 : *ptr1 = 0;
2729 : }
2730 : }
2731 50 : return szChain;
2732 : } /* End of MM_RemoveInitial_and_FinalQuotationMarks() */
2733 :
2734 84 : char *MM_RemoveLeadingWhitespaceOfString(char *szChain)
2735 : {
2736 : char *ptr;
2737 : char *ptr2;
2738 :
2739 84 : if (szChain == nullptr)
2740 0 : return szChain;
2741 :
2742 630 : for (ptr = szChain; *ptr && (*ptr == ' ' || *ptr == '\t'); ptr++)
2743 546 : continue;
2744 :
2745 84 : if (ptr != szChain)
2746 : {
2747 66 : ptr2 = szChain;
2748 534 : while (*ptr)
2749 : {
2750 468 : *ptr2 = *ptr;
2751 468 : ptr2++;
2752 468 : ptr++;
2753 : }
2754 66 : *ptr2 = 0;
2755 : }
2756 84 : return szChain;
2757 : }
2758 :
2759 15322 : char *MM_RemoveWhitespacesFromEndOfString(char *str)
2760 : {
2761 15322 : if (str == nullptr)
2762 0 : return str;
2763 15322 : return MM_l_RemoveWhitespacesFromEndOfString(str, strlen(str));
2764 : }
2765 :
2766 111 : struct MM_ID_GRAFIC_MULTIPLE_RECORD *MMCreateExtendedDBFIndex(
2767 : VSILFILE *f, MM_EXT_DBF_N_RECORDS nNumberOfRecords,
2768 : MM_FIRST_RECORD_OFFSET_TYPE offset_1era,
2769 : MM_ACCUMULATED_BYTES_TYPE_DBF bytes_per_fitxa,
2770 : MM_ACCUMULATED_BYTES_TYPE_DBF bytes_acumulats_id_grafic,
2771 : MM_BYTES_PER_FIELD_TYPE_DBF bytes_id_grafic, MM_BOOLEAN *isListField,
2772 : MM_EXT_DBF_N_RECORDS *nMaxN)
2773 : {
2774 : struct MM_ID_GRAFIC_MULTIPLE_RECORD *id;
2775 : MM_EXT_DBF_N_RECORDS i_dbf;
2776 : MM_EXT_DBF_SIGNED_N_RECORDS i, id_grafic;
2777 : char *fitxa;
2778 111 : MM_BYTES_PER_FIELD_TYPE_DBF bytes_final_id_principi_id1 =
2779 : bytes_per_fitxa - bytes_id_grafic;
2780 :
2781 111 : *isListField = FALSE;
2782 111 : *nMaxN = 0;
2783 111 : if (!nNumberOfRecords)
2784 9 : return nullptr; // No elements to read
2785 :
2786 102 : if (MMCheckSize_t(nNumberOfRecords, sizeof(*id)))
2787 0 : return nullptr;
2788 102 : if (nullptr == (id = (struct MM_ID_GRAFIC_MULTIPLE_RECORD *)VSICalloc(
2789 : (size_t)nNumberOfRecords, sizeof(*id))))
2790 0 : return nullptr;
2791 :
2792 102 : if (bytes_id_grafic == UINT32_MAX)
2793 : {
2794 0 : VSIFree(id);
2795 0 : CPLError(CE_Failure, CPLE_OutOfMemory, "Overflow in bytes_id_graphic");
2796 0 : return nullptr;
2797 : }
2798 :
2799 102 : if (nullptr == (fitxa = (char *)VSICalloc(1, (size_t)bytes_id_grafic + 1)))
2800 : {
2801 0 : VSIFree(id);
2802 0 : return nullptr;
2803 : }
2804 102 : fitxa[bytes_id_grafic] = '\0';
2805 :
2806 102 : VSIFSeekL(f,
2807 102 : (MM_FILE_OFFSET)offset_1era +
2808 102 : (MM_FILE_OFFSET)bytes_acumulats_id_grafic,
2809 : SEEK_SET);
2810 :
2811 102 : i_dbf = 0;
2812 : do
2813 : {
2814 102 : if (i_dbf == nNumberOfRecords ||
2815 102 : VSIFReadL(fitxa, 1, bytes_id_grafic, f) != (size_t)bytes_id_grafic)
2816 : {
2817 0 : VSIFree(id);
2818 0 : VSIFree(fitxa);
2819 0 : return nullptr;
2820 : }
2821 102 : i_dbf++;
2822 : } while (1 !=
2823 204 : sscanf(fitxa, scanf_MM_EXT_DBF_SIGNED_N_RECORDS, &id_grafic) ||
2824 102 : id_grafic < 0);
2825 102 : i = 0;
2826 :
2827 : while (TRUE)
2828 : {
2829 557 : if (i > id_grafic)
2830 : {
2831 0 : VSIFree(id);
2832 0 : VSIFree(fitxa);
2833 0 : return nullptr;
2834 : }
2835 557 : i = id_grafic;
2836 557 : if (i >= (MM_EXT_DBF_SIGNED_N_RECORDS)nNumberOfRecords)
2837 : {
2838 0 : VSIFree(fitxa);
2839 0 : return id;
2840 : }
2841 557 : id[(size_t)i].offset = (MM_FILE_OFFSET)offset_1era +
2842 557 : (MM_FILE_OFFSET)(i_dbf - 1) * bytes_per_fitxa;
2843 : do
2844 : {
2845 599 : id[(size_t)i].nMR++;
2846 599 : if (!(*isListField) && id[(size_t)i].nMR > 1)
2847 33 : *isListField = TRUE;
2848 599 : if (*nMaxN < id[(size_t)i].nMR)
2849 139 : *nMaxN = id[(size_t)i].nMR;
2850 :
2851 599 : if (i_dbf == nNumberOfRecords)
2852 : {
2853 102 : VSIFree(fitxa);
2854 102 : return id;
2855 : }
2856 497 : VSIFSeekL(f, bytes_final_id_principi_id1, SEEK_CUR);
2857 497 : if (VSIFReadL(fitxa, 1, bytes_id_grafic, f) !=
2858 : (size_t)bytes_id_grafic)
2859 : {
2860 0 : VSIFree(id);
2861 0 : VSIFree(fitxa);
2862 0 : return nullptr;
2863 : }
2864 497 : if (1 != sscanf(fitxa, scanf_MM_EXT_DBF_SIGNED_N_RECORDS,
2865 497 : &id_grafic) ||
2866 497 : id_grafic >= (MM_EXT_DBF_SIGNED_N_RECORDS)nNumberOfRecords)
2867 : {
2868 0 : VSIFree(fitxa);
2869 0 : return id;
2870 : }
2871 497 : i_dbf++;
2872 497 : } while (id_grafic == i);
2873 : }
2874 : } // End of MMCreateExtendedDBFIndex()
2875 :
2876 : // READING/CREATING MIRAMON METADATA
2877 : // Returns the value of an INI file. Used to read MiraMon metadata
2878 5330 : char *MMReturnValueFromSectionINIFile(const char *filename, const char *section,
2879 : const char *key)
2880 : {
2881 5330 : char *value = nullptr;
2882 : char *pszString;
2883 : const char *pszLine;
2884 5330 : char *section_header = nullptr;
2885 5330 : size_t key_len = 0;
2886 :
2887 5330 : VSILFILE *file = VSIFOpenL(filename, "rb");
2888 5330 : if (file == nullptr)
2889 : {
2890 0 : CPLError(CE_Failure, CPLE_OpenFailed, "Cannot open INI file %s.",
2891 : filename);
2892 0 : return nullptr;
2893 : }
2894 :
2895 5330 : if (key)
2896 5170 : key_len = strlen(key);
2897 :
2898 399455 : while ((pszLine = CPLReadLine2L(file, 10000, nullptr)) != nullptr)
2899 : {
2900 395828 : pszString = CPLRecode(pszLine, CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
2901 :
2902 : // Skip comments and empty lines
2903 395828 : if (*pszString == ';' || *pszString == '#' || *pszString == '\n' ||
2904 395828 : *pszString == '\r')
2905 : {
2906 0 : VSIFree(pszString);
2907 : // Move to next line
2908 0 : continue;
2909 : }
2910 :
2911 : // Check for section header
2912 395828 : if (*pszString == '[')
2913 : {
2914 86263 : char *section_end = strchr(pszString, ']');
2915 86263 : if (section_end != nullptr)
2916 : {
2917 86263 : *section_end = '\0'; // Terminate the string at ']'
2918 86263 : if (section_header)
2919 80933 : VSIFree(section_header);
2920 86263 : section_header = CPLStrdup(pszString + 1); // Skip the '['
2921 : }
2922 86263 : VSIFree(pszString);
2923 86263 : continue;
2924 : }
2925 :
2926 309565 : if (key)
2927 : {
2928 : // If the current line belongs to the desired section
2929 309405 : if (section_header != nullptr &&
2930 309405 : strcmp(section_header, section) == 0)
2931 : {
2932 : // Check if the line contains the desired key
2933 11366 : if (strncmp(pszString, key, key_len) == 0 &&
2934 1725 : pszString[key_len] == '=')
2935 : {
2936 : // Extract the value
2937 1543 : char *value_start = pszString + key_len + 1;
2938 1543 : char *value_end = strstr(value_start, "\r\n");
2939 1543 : if (value_end != nullptr)
2940 : {
2941 0 : *value_end =
2942 : '\0'; // Terminate the string at newline character if found
2943 : }
2944 : else
2945 : {
2946 1543 : value_end = strstr(value_start, "\n");
2947 1543 : if (value_end != nullptr)
2948 : {
2949 0 : *value_end =
2950 : '\0'; // Terminate the string at newline character if found
2951 : }
2952 : else
2953 : {
2954 1543 : value_end = strstr(value_start, "\r");
2955 1543 : if (value_end != nullptr)
2956 : {
2957 0 : *value_end =
2958 : '\0'; // Terminate the string at newline character if found
2959 : }
2960 : }
2961 : }
2962 :
2963 1543 : value = CPLStrdup(value_start);
2964 1543 : VSIFCloseL(file);
2965 1543 : VSIFree(section_header); // Free allocated memory
2966 1543 : VSIFree(pszString);
2967 1543 : return value;
2968 : }
2969 : }
2970 : }
2971 : else
2972 : {
2973 160 : if (section_header)
2974 : {
2975 160 : if (!strcmp(section_header, section))
2976 160 : value = section_header; // Freed out
2977 : else
2978 0 : value = nullptr;
2979 : }
2980 : else
2981 0 : value = nullptr;
2982 :
2983 160 : VSIFCloseL(file);
2984 160 : VSIFree(pszString);
2985 160 : return value;
2986 : }
2987 307862 : VSIFree(pszString);
2988 : }
2989 :
2990 3627 : if (section_header)
2991 3627 : VSIFree(section_header); // Free allocated memory
2992 3627 : VSIFCloseL(file);
2993 3627 : return value;
2994 : }
2995 :
2996 : // Retrieves EPSG codes from a CSV file based on provided geodetic identifiers.
2997 201 : int MMReturnCodeFromMM_m_idofic(char *pMMSRS_or_pSRS, char *szResult,
2998 : MM_BYTE direction)
2999 : {
3000 201 : char *aMMIDDBFFile = nullptr; //m_idofic.dbf
3001 201 : VSILFILE *pfMMSRS = nullptr;
3002 : const char *pszLine;
3003 : size_t nLong;
3004 : char *id_geodes, *psidgeodes, *epsg;
3005 :
3006 201 : if (!pMMSRS_or_pSRS)
3007 : {
3008 70 : return 1;
3009 : }
3010 :
3011 : {
3012 : #ifdef USE_ONLY_EMBEDDED_RESOURCE_FILES
3013 : const char *pszFilename = nullptr;
3014 : #else
3015 131 : const char *pszFilename = CPLFindFile("gdal", "MM_m_idofic.csv");
3016 : #endif
3017 : #ifdef EMBED_RESOURCE_FILES
3018 : if (!pszFilename || EQUAL(pszFilename, "MM_m_idofic.csv"))
3019 : {
3020 : pfMMSRS = VSIFileFromMemBuffer(
3021 : nullptr, (GByte *)(MiraMonGetMM_m_idofic_csv()),
3022 : (int)(strlen(MiraMonGetMM_m_idofic_csv())),
3023 : /* bTakeOwnership = */ false);
3024 : }
3025 : else
3026 : #endif
3027 131 : if (pszFilename)
3028 : {
3029 131 : aMMIDDBFFile = CPLStrdup(pszFilename);
3030 : }
3031 : }
3032 :
3033 : #ifdef EMBED_RESOURCE_FILES
3034 : if (!pfMMSRS)
3035 : #endif
3036 : {
3037 131 : if (!aMMIDDBFFile)
3038 : {
3039 0 : CPLError(CE_Failure, CPLE_OpenFailed,
3040 : "Error opening data\\MM_m_idofic.csv.\n");
3041 0 : return 1;
3042 : }
3043 :
3044 : // Opening the file with SRS information
3045 131 : if (nullptr == (pfMMSRS = VSIFOpenL(aMMIDDBFFile, "r")))
3046 : {
3047 0 : VSIFree(aMMIDDBFFile);
3048 0 : CPLError(CE_Failure, CPLE_OpenFailed,
3049 : "Error opening data\\MM_m_idofic.csv.\n");
3050 0 : return 1;
3051 : }
3052 131 : VSIFree(aMMIDDBFFile);
3053 : }
3054 :
3055 : // Checking the header of the csv file
3056 131 : pszLine = CPLReadLine2L(pfMMSRS, 10000, nullptr);
3057 :
3058 131 : if (!pszLine)
3059 :
3060 : {
3061 0 : VSIFCloseL(pfMMSRS);
3062 0 : CPLError(CE_Failure, CPLE_NotSupported,
3063 : "Wrong format in data\\MM_m_idofic.csv.\n");
3064 0 : return 1;
3065 : }
3066 131 : id_geodes = MM_stristr(pszLine, "ID_GEODES");
3067 131 : if (!id_geodes)
3068 : {
3069 0 : VSIFCloseL(pfMMSRS);
3070 0 : CPLError(CE_Failure, CPLE_NotSupported,
3071 : "Wrong format in data\\MM_m_idofic.csv.\n");
3072 0 : return 1;
3073 : }
3074 131 : id_geodes[strlen("ID_GEODES")] = '\0';
3075 131 : psidgeodes = MM_stristr(pszLine, "PSIDGEODES");
3076 131 : if (!psidgeodes)
3077 : {
3078 0 : VSIFCloseL(pfMMSRS);
3079 0 : CPLError(CE_Failure, CPLE_NotSupported,
3080 : "Wrong format in data\\MM_m_idofic.csv.\n");
3081 0 : return 1;
3082 : }
3083 131 : psidgeodes[strlen("PSIDGEODES")] = '\0';
3084 :
3085 : // Is PSIDGEODES in first place?
3086 131 : if (strncmp(pszLine, psidgeodes, strlen("PSIDGEODES")))
3087 : {
3088 0 : VSIFCloseL(pfMMSRS);
3089 0 : CPLError(CE_Failure, CPLE_NotSupported,
3090 : "Wrong format in data\\MM_m_idofic.csv.\n");
3091 0 : return 1;
3092 : }
3093 : // Is ID_GEODES after PSIDGEODES?
3094 131 : if (strncmp(pszLine + strlen("PSIDGEODES") + 1, "ID_GEODES",
3095 : strlen("ID_GEODES")))
3096 : {
3097 0 : VSIFCloseL(pfMMSRS);
3098 0 : CPLError(CE_Failure, CPLE_NotSupported,
3099 : "Wrong format in data\\MM_m_idofic.csv.\n");
3100 0 : return 1;
3101 : }
3102 :
3103 : // Looking for the information.
3104 34994 : while ((pszLine = CPLReadLine2L(pfMMSRS, 10000, nullptr)) != nullptr)
3105 : {
3106 34943 : id_geodes = strstr(pszLine, ";");
3107 34943 : if (!id_geodes)
3108 : {
3109 0 : VSIFCloseL(pfMMSRS);
3110 0 : CPLError(CE_Failure, CPLE_NotSupported,
3111 : "Wrong format in data\\MM_m_idofic.csv.\n");
3112 0 : return 1;
3113 : }
3114 :
3115 34943 : psidgeodes = strstr(id_geodes + 1, ";");
3116 34943 : if (!psidgeodes)
3117 : {
3118 0 : VSIFCloseL(pfMMSRS);
3119 0 : CPLError(CE_Failure, CPLE_NotSupported,
3120 : "Wrong format in data\\MM_m_idofic.csv.\n");
3121 0 : return 1;
3122 : }
3123 :
3124 34943 : id_geodes[(ptrdiff_t)psidgeodes - (ptrdiff_t)id_geodes] = '\0';
3125 34943 : psidgeodes = CPLStrdup(pszLine);
3126 34943 : psidgeodes[(ptrdiff_t)id_geodes - (ptrdiff_t)pszLine] = '\0';
3127 34943 : id_geodes++;
3128 :
3129 34943 : if (direction == EPSG_FROM_MMSRS)
3130 : {
3131 : // I have pMMSRS and I want pSRS
3132 30690 : if (strcmp(pMMSRS_or_pSRS, id_geodes))
3133 : {
3134 30630 : VSIFree(psidgeodes);
3135 30630 : continue;
3136 : }
3137 :
3138 60 : epsg = strstr(psidgeodes, "EPSG:");
3139 60 : nLong = strlen("EPSG:");
3140 60 : if (epsg && !strncmp(epsg, psidgeodes, nLong))
3141 : {
3142 60 : if (epsg[nLong] != '\0')
3143 : {
3144 60 : strcpy(szResult, epsg + nLong);
3145 60 : VSIFree(psidgeodes);
3146 60 : VSIFCloseL(pfMMSRS);
3147 60 : return 0; // found
3148 : }
3149 : else
3150 : {
3151 0 : VSIFCloseL(pfMMSRS);
3152 0 : *szResult = '\0';
3153 0 : VSIFree(psidgeodes);
3154 0 : return 1; // not found
3155 : }
3156 : }
3157 : }
3158 : else
3159 : {
3160 : // I have pSRS and I want pMMSRS
3161 4253 : epsg = strstr(psidgeodes, "EPSG:");
3162 4253 : nLong = strlen("EPSG:");
3163 4253 : if (epsg && !strncmp(epsg, psidgeodes, nLong))
3164 : {
3165 3336 : if (epsg[nLong] != '\0')
3166 : {
3167 3336 : if (!strcmp(pMMSRS_or_pSRS, epsg + nLong))
3168 : {
3169 20 : strcpy(szResult, id_geodes);
3170 20 : VSIFCloseL(pfMMSRS);
3171 20 : VSIFree(psidgeodes);
3172 20 : return 0; // found
3173 : }
3174 : }
3175 : }
3176 : }
3177 4233 : VSIFree(psidgeodes);
3178 : }
3179 :
3180 51 : VSIFCloseL(pfMMSRS);
3181 51 : return 1; // not found
3182 : }
3183 :
3184 : // Verifies the version of a MiraMon REL 4 file.
3185 163 : int MMCheck_REL_FILE(const char *szREL_file)
3186 : {
3187 : char *pszLine;
3188 : VSILFILE *pF;
3189 :
3190 : // Does the REL file exist?
3191 163 : pF = VSIFOpenL(szREL_file, "r");
3192 163 : if (!pF)
3193 : {
3194 3 : CPLError(CE_Failure, CPLE_OpenFailed, "The file %s must exist.",
3195 : szREL_file);
3196 3 : return 1;
3197 : }
3198 160 : VSIFCloseL(pF);
3199 :
3200 : // Does the REL file have VERSION?
3201 : pszLine =
3202 160 : MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO, nullptr);
3203 160 : if (!pszLine)
3204 : {
3205 0 : CPLError(CE_Failure, CPLE_OpenFailed,
3206 : "The file \"%s\" must be REL4. "
3207 : "You can use ConvREL.exe from MiraMon software "
3208 : " or GeM+ "
3209 : "to convert this file to REL4.",
3210 : szREL_file);
3211 0 : return 1;
3212 : }
3213 160 : VSIFree(pszLine);
3214 :
3215 : // Does the REL file have the correct VERSION?
3216 : // Vers>=4?
3217 : pszLine =
3218 160 : MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO, KEY_Vers);
3219 160 : if (pszLine)
3220 : {
3221 160 : if (*pszLine == '\0' || atoi(pszLine) < (int)MM_VERS)
3222 : {
3223 0 : CPLError(CE_Failure, CPLE_OpenFailed,
3224 : "The file \"%s\" must have %s>=%d.", szREL_file, KEY_Vers,
3225 : MM_VERS);
3226 0 : VSIFree(pszLine);
3227 0 : return 1;
3228 : }
3229 160 : VSIFree(pszLine);
3230 : }
3231 : else
3232 : {
3233 0 : CPLError(CE_Failure, CPLE_OpenFailed,
3234 : "The file \"%s\" must have %s>=%d.", szREL_file, KEY_Vers,
3235 : MM_VERS);
3236 0 : return 1;
3237 : }
3238 :
3239 : // SubVers>=0?
3240 160 : pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO,
3241 : KEY_SubVers);
3242 160 : if (pszLine)
3243 : {
3244 160 : if (*pszLine == '\0' || atoi(pszLine) < (int)MM_SUBVERS_ACCEPTED)
3245 : {
3246 0 : CPLError(CE_Failure, CPLE_OpenFailed,
3247 : "The file \"%s\" must have %s>=%d.", szREL_file,
3248 : KEY_SubVers, MM_SUBVERS_ACCEPTED);
3249 :
3250 0 : VSIFree(pszLine);
3251 0 : return 1;
3252 : }
3253 160 : VSIFree(pszLine);
3254 : }
3255 : else
3256 : {
3257 0 : CPLError(CE_Failure, CPLE_OpenFailed,
3258 : "The file \"%s\" must have %s>=%d.", szREL_file, KEY_SubVers,
3259 : MM_SUBVERS_ACCEPTED);
3260 0 : return 1;
3261 : }
3262 :
3263 : // VersMetaDades>=4?
3264 160 : pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO,
3265 : KEY_VersMetaDades);
3266 160 : if (pszLine)
3267 : {
3268 160 : if (*pszLine == '\0' || atoi(pszLine) < (int)MM_VERS_METADADES_ACCEPTED)
3269 : {
3270 0 : CPLError(CE_Failure, CPLE_OpenFailed,
3271 : "The file \"%s\" must have %s>=%d.", szREL_file,
3272 : KEY_VersMetaDades, MM_VERS_METADADES_ACCEPTED);
3273 0 : VSIFree(pszLine);
3274 0 : return 1;
3275 : }
3276 160 : VSIFree(pszLine);
3277 : }
3278 : else
3279 : {
3280 0 : CPLError(CE_Failure, CPLE_OpenFailed,
3281 : "The file \"%s\" must have %s>=%d.", szREL_file,
3282 : KEY_VersMetaDades, MM_VERS_METADADES_ACCEPTED);
3283 0 : return 1;
3284 : }
3285 :
3286 : // SubVersMetaDades>=0?
3287 160 : pszLine = MMReturnValueFromSectionINIFile(szREL_file, SECTION_VERSIO,
3288 : KEY_SubVersMetaDades);
3289 160 : if (pszLine)
3290 : {
3291 160 : if (*pszLine == '\0' || atoi(pszLine) < (int)MM_SUBVERS_METADADES)
3292 : {
3293 0 : CPLError(CE_Failure, CPLE_OpenFailed,
3294 : "The file \"%s\" must have %s>=%d.", szREL_file,
3295 : KEY_SubVersMetaDades, MM_SUBVERS_METADADES);
3296 0 : VSIFree(pszLine);
3297 0 : return 1;
3298 : }
3299 160 : VSIFree(pszLine);
3300 : }
3301 : else
3302 : {
3303 0 : CPLError(CE_Failure, CPLE_OpenFailed,
3304 : "The file \"%s\" must have %s>=%d.", szREL_file,
3305 : KEY_SubVersMetaDades, MM_SUBVERS_METADADES);
3306 0 : return 1;
3307 : }
3308 160 : return 0;
3309 : }
3310 :
3311 : CPL_C_END // Necessary for compiling in GDAL project
|