Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- Fix MDEV-22561 Unable to access DBF inside a ZIP archive
  modified:   storage/connect/filamdbf.cpp
  modified:   storage/connect/filamdbf.h
  modified:   storage/connect/filamzip.cpp
  modified:   storage/connect/filamzip.h
  modified:   storage/connect/ha_connect.cc
  modified:   storage/connect/plgxml.cpp
  modified:   storage/connect/tabdos.cpp
  modified:   storage/connect/tabdos.h
  modified:   storage/connect/tabfix.h

- Add/Init Level class member
  modified:   storage/connect/mongo.cpp
  modified:   storage/connect/mongo.h
  modified:   storage/connect/tabjson.cpp
  modified:   storage/connect/tabjson.h

- Typo
  modified:   storage/connect/connect.cc
  • Loading branch information
Buggynours committed Jul 13, 2020
1 parent 2654ddd commit 1e07df9
Show file tree
Hide file tree
Showing 14 changed files with 490 additions and 100 deletions.
1 change: 0 additions & 1 deletion storage/connect/connect.cc
Expand Up @@ -355,7 +355,6 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
} // endif mode

rcop = false;

} catch (int n) {
if (trace(1))
htrc("Exception %d: %s\n", n, g->Message);
Expand Down
199 changes: 147 additions & 52 deletions storage/connect/filamdbf.cpp
Expand Up @@ -49,6 +49,7 @@
#include "global.h"
#include "plgdbsem.h"
#include "filamdbf.h"
#include "filamzip.h"
#include "tabdos.h"
#include "valblk.h"
#define NO_FUNC
Expand Down Expand Up @@ -139,7 +140,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
if (fread(buf, HEADLEN, 1, file) != 1) {
strcpy(g->Message, MSG(NO_READ_32));
return RC_NF;
} // endif fread
} // endif fread

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

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

if (fread(&endmark, 2, 1, file) != 1) {
strcpy(g->Message, MSG(BAD_HEAD_END));
return RC_FX;
} // endif fread
} // endif fread

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

} // endif endmark
} // endif endmark

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

/****************************************************************************/
/* dbfields: Analyze a DBF header and set the table fields number. */
/* Parameters: */
/* PGLOBAL g -- pointer to the CONNECT Global structure */
/* DBFHEADER *hdrp -- pointer to _dbfheader structure */
/* Returns: */
/* RC_OK, RC_INFO, or RC_FX if error. */
/****************************************************************************/
int dbfields(PGLOBAL g, DBFHEADER* hdrp)
{
char* endmark;
int dbc = 2, rc = RC_OK;

*g->Message = '\0';

// Check first byte to be sure of .dbf type
if ((hdrp->Version & 0x03) != DBFTYPE) {
strcpy(g->Message, MSG(NOT_A_DBF_FILE));
rc = RC_INFO;

if ((hdrp->Version & 0x30) == 0x30) {
strcpy(g->Message, MSG(FOXPRO_FILE));
dbc = 264; // FoxPro database container
} // endif Version

} else
strcpy(g->Message, MSG(DBASE_FILE));

// Check last byte(s) of header
endmark = (char*)hdrp + hdrp->Headlen() - dbc;

// Some headers just have 1D others have 1D00 following fields
if (endmark[0] != EOH && endmark[1] != EOH) {
sprintf(g->Message, MSG(NO_0DH_HEAD), dbc);

if (rc == RC_OK)
return RC_FX;

} // endif endmark

// Calculate here the number of fields while we have the dbc info
hdrp->SetFields((hdrp->Headlen() - dbc - 1) / 32);
return rc;
} // end of dbfields

/* -------------------------- Function DBFColumns ------------------------- */

/****************************************************************************/
/* DBFColumns: constructs the result blocks containing the description */
/* of all the columns of a DBF file that will be retrieved by #GetData. */
/****************************************************************************/
PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, PTOS topt, bool info)
{
int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
Expand All @@ -196,10 +242,12 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
char buf[2], filename[_MAX_PATH];
int ncol = sizeof(buftyp) / sizeof(int);
int rc, type, len, field, fields;
bool bad;
DBFHEADER mainhead;
DESCRIPTOR thisfield;
FILE *infile = NULL;
bool bad, mul;
PCSZ target, pwd;
DBFHEADER mainhead, *hp;
DESCRIPTOR thisfield, *tfp;
FILE *infile = NULL;
UNZIPUTL *zutp = NULL;
PQRYRES qrp;
PCOLRES crp;

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

if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb")))
return NULL;

/************************************************************************/
/* Get the first 32 bytes of the header. */
/************************************************************************/
if ((rc = dbfhead(g, infile, filename, &mainhead)) == RC_FX) {
fclose(infile);
return NULL;
} // endif dbfhead

/************************************************************************/
/* Allocate the structures used to refer to the result set. */
/************************************************************************/
fields = mainhead.Fields();
if (topt->zipped) {
target = GetStringTableOption(g, topt, "Entry", NULL);
mul = (target && *target) ? strchr(target, '*') || strchr(target, '?')
: false;
mul = GetBooleanTableOption(g, topt, "Mulentries", mul);

if (mul) {
strcpy(g->Message, "Cannot find column definition for multiple entries");
return NULL;
} // endif Multiple

pwd = GetStringTableOption(g, topt, "Password", NULL);
zutp = new(g) UNZIPUTL(target, pwd, mul);

if (!zutp->OpenTable(g, MODE_READ, filename))
hp = (DBFHEADER*)zutp->memory;
else
return NULL;

/**********************************************************************/
/* Set the table fields number. */
/**********************************************************************/
if ((rc = dbfields(g, hp)) == RC_FX) {
zutp->close();
return NULL;
} // endif dbfields

tfp = (DESCRIPTOR*)hp;
} else {
if (!(infile = global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb")))
return NULL;
else
hp = &mainhead;

/**********************************************************************/
/* Get the first 32 bytes of the header. */
/**********************************************************************/
if ((rc = dbfhead(g, infile, filename, hp)) == RC_FX) {
fclose(infile);
return NULL;
} // endif dbfhead

tfp = &thisfield;
} // endif zipped

/************************************************************************/
/* Get the number of the table fields. */
/************************************************************************/
fields = hp->Fields();
} else
fields = 0;

Expand All @@ -241,19 +323,21 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
if (info || !qrp) {
if (infile)
fclose(infile);
else if (zutp)
zutp->close();

return qrp;
} // endif info
} // endif info

if (trace(1)) {
htrc("Structure of %s\n", filename);
htrc("headlen=%hd reclen=%hd degree=%d\n",
mainhead.Headlen(), mainhead.Reclen(), fields);
htrc("flags(iem)=%d,%d,%d cp=%d\n", mainhead.Incompleteflag,
mainhead.Encryptflag, mainhead.Mdxflag, mainhead.Language);
hp->Headlen(), hp->Reclen(), fields);
htrc("flags(iem)=%d,%d,%d cp=%d\n", hp->Incompleteflag,
hp->Encryptflag, hp->Mdxflag, hp->Language);
htrc("%hd records, last changed %02d/%02d/%d\n",
mainhead.Records(), mainhead.Filedate[1], mainhead.Filedate[2],
mainhead.Filedate[0] + (mainhead.Filedate[0] <= 30) ? 2000 : 1900);
hp->Records(), hp->Filedate[1], hp->Filedate[2],
hp->Filedate[0] + (hp->Filedate[0] <= 30) ? 2000 : 1900);
htrc("Field Type Offset Len Dec Set Mdx\n");
} // endif trace

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

if (fread(&thisfield, HEADLEN, 1, infile) != 1) {
if (topt->zipped) {
tfp = (DESCRIPTOR*)((char*)tfp + HEADLEN);
} else if (fread(tfp, HEADLEN, 1, infile) != 1) {
sprintf(g->Message, MSG(ERR_READING_REC), field+1, fn);
goto err;
} else
len = thisfield.Length;
} // endif fread

len = tfp->Length;

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

/************************************************************************/
/* Now get the results into blocks. */
/************************************************************************/
switch (thisfield.Type) {
switch (tfp->Type) {
case 'C': // Characters
case 'L': // Logical 'T' or 'F' or space
type = TYPE_STRING;
Expand All @@ -294,7 +381,7 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
// type = TYPE_INT;
// break;
case 'N':
type = (thisfield.Decimals) ? TYPE_DOUBLE
type = (tfp->Decimals) ? TYPE_DOUBLE
: (len > 10) ? TYPE_BIGINT : TYPE_INT;
break;
case 'F': // Float
Expand All @@ -306,8 +393,8 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
break;
default:
if (!info) {
sprintf(g->Message, MSG(BAD_DBF_TYPE), thisfield.Type
, thisfield.Name);
sprintf(g->Message, MSG(BAD_DBF_TYPE), tfp->Type
, tfp->Name);
goto err;
} // endif info

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

crp = qrp->Colresp; // Column Name
crp->Kdata->SetValue(thisfield.Name, field);
crp->Kdata->SetValue(tfp->Name, field);
crp = crp->Next; // Data Type
crp->Kdata->SetValue((int)type, field);
crp = crp->Next; // Type Name

if (bad) {
buf[0] = thisfield.Type;
buf[0] = tfp->Type;
crp->Kdata->SetValue(buf, field);
} else
crp->Kdata->SetValue(GetTypeName(type), field);

crp = crp->Next; // Precision
crp->Kdata->SetValue((int)thisfield.Length, field);
crp->Kdata->SetValue((int)tfp->Length, field);
crp = crp->Next; // Length
crp->Kdata->SetValue((int)thisfield.Length, field);
crp->Kdata->SetValue((int)tfp->Length, field);
crp = crp->Next; // Scale (precision)
crp->Kdata->SetValue((int)thisfield.Decimals, field);
crp->Kdata->SetValue((int)tfp->Decimals, field);
} // endfor field

qrp->Nblin = field;
fclose(infile);

if (infile)
fclose(infile);
else if (zutp)
zutp->close();

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

sprintf(buf,
"Ver=%02x ncol=%hu nlin=%u lrecl=%hu headlen=%hu date=%02d/%02d/%02d",
mainhead.Version, fields, mainhead.Records, mainhead.Reclen,
mainhead.Headlen, mainhead.Filedate[0], mainhead.Filedate[1],
mainhead.Filedate[2]);
hp->Version, fields, hp->Records, hp->Reclen,
hp->Headlen, hp->Filedate[0], hp->Filedate[1],
hp->Filedate[2]);

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

err:
fclose(infile);
return NULL;
err:
if (infile)
fclose(infile);
else if (zutp)
zutp->close();

return NULL;
} // end of DBFColumns

/* ---------------------------- Class DBFBASE ----------------------------- */
Expand Down
2 changes: 1 addition & 1 deletion storage/connect/filamdbf.h
Expand Up @@ -19,7 +19,7 @@ typedef class DBMFAM *PDBMFAM;
/****************************************************************************/
/* Functions used externally. */
/****************************************************************************/
PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info);
PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, PTOS tiop, bool info);

/****************************************************************************/
/* This is the base class for dBASE file access methods. */
Expand Down

0 comments on commit 1e07df9

Please sign in to comment.