Skip to content

Commit 6d8af36

Browse files
committed
Merge remote-tracking branch 'connect/10.2' into 10.2
2 parents ef7cb0a + ad0d242 commit 6d8af36

17 files changed

+505
-102
lines changed

storage/connect/connect.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,6 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
355355
} // endif mode
356356

357357
rcop = false;
358-
359358
} catch (int n) {
360359
if (trace(1))
361360
htrc("Exception %d: %s\n", n, g->Message);

storage/connect/filamdbf.cpp

Lines changed: 147 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "global.h"
5050
#include "plgdbsem.h"
5151
#include "filamdbf.h"
52+
#include "filamzip.h"
5253
#include "tabdos.h"
5354
#include "valblk.h"
5455
#define NO_FUNC
@@ -139,7 +140,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
139140
if (fread(buf, HEADLEN, 1, file) != 1) {
140141
strcpy(g->Message, MSG(NO_READ_32));
141142
return RC_NF;
142-
} // endif fread
143+
} // endif fread
143144

144145
// Check first byte to be sure of .dbf type
145146
if ((buf->Version & 0x03) != DBFTYPE) {
@@ -149,7 +150,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
149150
if ((buf->Version & 0x30) == 0x30) {
150151
strcpy(g->Message, MSG(FOXPRO_FILE));
151152
dbc = 264; // FoxPro database container
152-
} // endif Version
153+
} // endif Version
153154

154155
} else
155156
strcpy(g->Message, MSG(DBASE_FILE));
@@ -158,12 +159,12 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
158159
if (fseek(file, buf->Headlen() - dbc, SEEK_SET) != 0) {
159160
sprintf(g->Message, MSG(BAD_HEADER), fn);
160161
return RC_FX;
161-
} // endif fseek
162+
} // endif fseek
162163

163164
if (fread(&endmark, 2, 1, file) != 1) {
164165
strcpy(g->Message, MSG(BAD_HEAD_END));
165166
return RC_FX;
166-
} // endif fread
167+
} // endif fread
167168

168169
// Some files have just 1D others have 1D00 following fields
169170
if (endmark[0] != EOH && endmark[1] != EOH) {
@@ -172,21 +173,66 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
172173
if (rc == RC_OK)
173174
return RC_FX;
174175

175-
} // endif endmark
176+
} // endif endmark
176177

177178
// Calculate here the number of fields while we have the dbc info
178179
buf->SetFields((buf->Headlen() - dbc - 1) / 32);
179180
fseek(file, HEADLEN, SEEK_SET);
180181
return rc;
181182
} // end of dbfhead
182183

184+
/****************************************************************************/
185+
/* dbfields: Analyze a DBF header and set the table fields number. */
186+
/* Parameters: */
187+
/* PGLOBAL g -- pointer to the CONNECT Global structure */
188+
/* DBFHEADER *hdrp -- pointer to _dbfheader structure */
189+
/* Returns: */
190+
/* RC_OK, RC_INFO, or RC_FX if error. */
191+
/****************************************************************************/
192+
static int dbfields(PGLOBAL g, DBFHEADER* hdrp)
193+
{
194+
char* endmark;
195+
int dbc = 2, rc = RC_OK;
196+
197+
*g->Message = '\0';
198+
199+
// Check first byte to be sure of .dbf type
200+
if ((hdrp->Version & 0x03) != DBFTYPE) {
201+
strcpy(g->Message, MSG(NOT_A_DBF_FILE));
202+
rc = RC_INFO;
203+
204+
if ((hdrp->Version & 0x30) == 0x30) {
205+
strcpy(g->Message, MSG(FOXPRO_FILE));
206+
dbc = 264; // FoxPro database container
207+
} // endif Version
208+
209+
} else
210+
strcpy(g->Message, MSG(DBASE_FILE));
211+
212+
// Check last byte(s) of header
213+
endmark = (char*)hdrp + hdrp->Headlen() - dbc;
214+
215+
// Some headers just have 1D others have 1D00 following fields
216+
if (endmark[0] != EOH && endmark[1] != EOH) {
217+
sprintf(g->Message, MSG(NO_0DH_HEAD), dbc);
218+
219+
if (rc == RC_OK)
220+
return RC_FX;
221+
222+
} // endif endmark
223+
224+
// Calculate here the number of fields while we have the dbc info
225+
hdrp->SetFields((hdrp->Headlen() - dbc - 1) / 32);
226+
return rc;
227+
} // end of dbfields
228+
183229
/* -------------------------- Function DBFColumns ------------------------- */
184230

185231
/****************************************************************************/
186232
/* DBFColumns: constructs the result blocks containing the description */
187233
/* of all the columns of a DBF file that will be retrieved by #GetData. */
188234
/****************************************************************************/
189-
PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
235+
PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, PTOS topt, bool info)
190236
{
191237
int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
192238
TYPE_INT, TYPE_INT, TYPE_SHORT};
@@ -196,10 +242,12 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
196242
char buf[2], filename[_MAX_PATH];
197243
int ncol = sizeof(buftyp) / sizeof(int);
198244
int rc, type, len, field, fields;
199-
bool bad;
200-
DBFHEADER mainhead;
201-
DESCRIPTOR thisfield;
202-
FILE *infile = NULL;
245+
bool bad, mul;
246+
PCSZ target, pwd;
247+
DBFHEADER mainhead, *hp;
248+
DESCRIPTOR thisfield, *tfp;
249+
FILE *infile = NULL;
250+
UNZIPUTL *zutp = NULL;
203251
PQRYRES qrp;
204252
PCOLRES crp;
205253

@@ -217,21 +265,55 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
217265
/************************************************************************/
218266
PlugSetPath(filename, fn, dp);
219267

220-
if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb")))
221-
return NULL;
222-
223-
/************************************************************************/
224-
/* Get the first 32 bytes of the header. */
225-
/************************************************************************/
226-
if ((rc = dbfhead(g, infile, filename, &mainhead)) == RC_FX) {
227-
fclose(infile);
228-
return NULL;
229-
} // endif dbfhead
230-
231-
/************************************************************************/
232-
/* Allocate the structures used to refer to the result set. */
233-
/************************************************************************/
234-
fields = mainhead.Fields();
268+
if (topt->zipped) {
269+
target = GetStringTableOption(g, topt, "Entry", NULL);
270+
mul = (target && *target) ? strchr(target, '*') || strchr(target, '?')
271+
: false;
272+
mul = GetBooleanTableOption(g, topt, "Mulentries", mul);
273+
274+
if (mul) {
275+
strcpy(g->Message, "Cannot find column definition for multiple entries");
276+
return NULL;
277+
} // endif Multiple
278+
279+
pwd = GetStringTableOption(g, topt, "Password", NULL);
280+
zutp = new(g) UNZIPUTL(target, pwd, mul);
281+
282+
if (!zutp->OpenTable(g, MODE_READ, filename))
283+
hp = (DBFHEADER*)zutp->memory;
284+
else
285+
return NULL;
286+
287+
/**********************************************************************/
288+
/* Set the table fields number. */
289+
/**********************************************************************/
290+
if ((rc = dbfields(g, hp)) == RC_FX) {
291+
zutp->close();
292+
return NULL;
293+
} // endif dbfields
294+
295+
tfp = (DESCRIPTOR*)hp;
296+
} else {
297+
if (!(infile = global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb")))
298+
return NULL;
299+
else
300+
hp = &mainhead;
301+
302+
/**********************************************************************/
303+
/* Get the first 32 bytes of the header. */
304+
/**********************************************************************/
305+
if ((rc = dbfhead(g, infile, filename, hp)) == RC_FX) {
306+
fclose(infile);
307+
return NULL;
308+
} // endif dbfhead
309+
310+
tfp = &thisfield;
311+
} // endif zipped
312+
313+
/************************************************************************/
314+
/* Get the number of the table fields. */
315+
/************************************************************************/
316+
fields = hp->Fields();
235317
} else
236318
fields = 0;
237319

@@ -241,19 +323,21 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
241323
if (info || !qrp) {
242324
if (infile)
243325
fclose(infile);
326+
else if (zutp)
327+
zutp->close();
244328

245329
return qrp;
246-
} // endif info
330+
} // endif info
247331

248332
if (trace(1)) {
249333
htrc("Structure of %s\n", filename);
250334
htrc("headlen=%hd reclen=%hd degree=%d\n",
251-
mainhead.Headlen(), mainhead.Reclen(), fields);
252-
htrc("flags(iem)=%d,%d,%d cp=%d\n", mainhead.Incompleteflag,
253-
mainhead.Encryptflag, mainhead.Mdxflag, mainhead.Language);
335+
hp->Headlen(), hp->Reclen(), fields);
336+
htrc("flags(iem)=%d,%d,%d cp=%d\n", hp->Incompleteflag,
337+
hp->Encryptflag, hp->Mdxflag, hp->Language);
254338
htrc("%hd records, last changed %02d/%02d/%d\n",
255-
mainhead.Records(), mainhead.Filedate[1], mainhead.Filedate[2],
256-
mainhead.Filedate[0] + (mainhead.Filedate[0] <= 30) ? 2000 : 1900);
339+
hp->Records(), hp->Filedate[1], hp->Filedate[2],
340+
hp->Filedate[0] + (hp->Filedate[0] <= 30) ? 2000 : 1900);
257341
htrc("Field Type Offset Len Dec Set Mdx\n");
258342
} // endif trace
259343

@@ -265,21 +349,24 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
265349
for (field = 0; field < fields; field++) {
266350
bad = FALSE;
267351

268-
if (fread(&thisfield, HEADLEN, 1, infile) != 1) {
352+
if (topt->zipped) {
353+
tfp = (DESCRIPTOR*)((char*)tfp + HEADLEN);
354+
} else if (fread(tfp, HEADLEN, 1, infile) != 1) {
269355
sprintf(g->Message, MSG(ERR_READING_REC), field+1, fn);
270356
goto err;
271-
} else
272-
len = thisfield.Length;
357+
} // endif fread
358+
359+
len = tfp->Length;
273360

274361
if (trace(1))
275362
htrc("%-11s %c %6ld %3d %2d %3d %3d\n",
276-
thisfield.Name, thisfield.Type, thisfield.Offset, len,
277-
thisfield.Decimals, thisfield.Setfield, thisfield.Mdxfield);
363+
tfp->Name, tfp->Type, tfp->Offset, len,
364+
tfp->Decimals, tfp->Setfield, tfp->Mdxfield);
278365

279366
/************************************************************************/
280367
/* Now get the results into blocks. */
281368
/************************************************************************/
282-
switch (thisfield.Type) {
369+
switch (tfp->Type) {
283370
case 'C': // Characters
284371
case 'L': // Logical 'T' or 'F' or space
285372
type = TYPE_STRING;
@@ -294,7 +381,7 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
294381
// type = TYPE_INT;
295382
// break;
296383
case 'N':
297-
type = (thisfield.Decimals) ? TYPE_DOUBLE
384+
type = (tfp->Decimals) ? TYPE_DOUBLE
298385
: (len > 10) ? TYPE_BIGINT : TYPE_INT;
299386
break;
300387
case 'F': // Float
@@ -306,8 +393,8 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
306393
break;
307394
default:
308395
if (!info) {
309-
sprintf(g->Message, MSG(BAD_DBF_TYPE), thisfield.Type
310-
, thisfield.Name);
396+
sprintf(g->Message, MSG(BAD_DBF_TYPE), tfp->Type
397+
, tfp->Name);
311398
goto err;
312399
} // endif info
313400

@@ -316,27 +403,31 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
316403
} // endswitch Type
317404

318405
crp = qrp->Colresp; // Column Name
319-
crp->Kdata->SetValue(thisfield.Name, field);
406+
crp->Kdata->SetValue(tfp->Name, field);
320407
crp = crp->Next; // Data Type
321408
crp->Kdata->SetValue((int)type, field);
322409
crp = crp->Next; // Type Name
323410

324411
if (bad) {
325-
buf[0] = thisfield.Type;
412+
buf[0] = tfp->Type;
326413
crp->Kdata->SetValue(buf, field);
327414
} else
328415
crp->Kdata->SetValue(GetTypeName(type), field);
329416

330417
crp = crp->Next; // Precision
331-
crp->Kdata->SetValue((int)thisfield.Length, field);
418+
crp->Kdata->SetValue((int)tfp->Length, field);
332419
crp = crp->Next; // Length
333-
crp->Kdata->SetValue((int)thisfield.Length, field);
420+
crp->Kdata->SetValue((int)tfp->Length, field);
334421
crp = crp->Next; // Scale (precision)
335-
crp->Kdata->SetValue((int)thisfield.Decimals, field);
422+
crp->Kdata->SetValue((int)tfp->Decimals, field);
336423
} // endfor field
337424

338425
qrp->Nblin = field;
339-
fclose(infile);
426+
427+
if (infile)
428+
fclose(infile);
429+
else if (zutp)
430+
zutp->close();
340431

341432
#if 0
342433
if (info) {
@@ -347,9 +438,9 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
347438

348439
sprintf(buf,
349440
"Ver=%02x ncol=%hu nlin=%u lrecl=%hu headlen=%hu date=%02d/%02d/%02d",
350-
mainhead.Version, fields, mainhead.Records, mainhead.Reclen,
351-
mainhead.Headlen, mainhead.Filedate[0], mainhead.Filedate[1],
352-
mainhead.Filedate[2]);
441+
hp->Version, fields, hp->Records, hp->Reclen,
442+
hp->Headlen, hp->Filedate[0], hp->Filedate[1],
443+
hp->Filedate[2]);
353444

354445
strcat(g->Message, buf);
355446
} // endif info
@@ -360,9 +451,13 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
360451
/**************************************************************************/
361452
return qrp;
362453

363-
err:
364-
fclose(infile);
365-
return NULL;
454+
err:
455+
if (infile)
456+
fclose(infile);
457+
else if (zutp)
458+
zutp->close();
459+
460+
return NULL;
366461
} // end of DBFColumns
367462

368463
/* ---------------------------- Class DBFBASE ----------------------------- */

storage/connect/filamdbf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ typedef class DBMFAM *PDBMFAM;
1919
/****************************************************************************/
2020
/* Functions used externally. */
2121
/****************************************************************************/
22-
PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info);
22+
PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, PTOS tiop, bool info);
2323

2424
/****************************************************************************/
2525
/* This is the base class for dBASE file access methods. */

0 commit comments

Comments
 (0)