summaryrefslogtreecommitdiff
path: root/storage/connect/filamdbf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/connect/filamdbf.cpp')
-rw-r--r--storage/connect/filamdbf.cpp199
1 files changed, 147 insertions, 52 deletions
diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp
index c8bab2b53a4..542159fd172 100644
--- a/storage/connect/filamdbf.cpp
+++ b/storage/connect/filamdbf.cpp
@@ -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
@@ -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) {
@@ -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));
@@ -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) {
@@ -172,7 +173,7 @@ 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);
@@ -180,13 +181,58 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
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. */
+/****************************************************************************/
+static 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};
@@ -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;
@@ -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;
@@ -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
@@ -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;
@@ -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
@@ -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
@@ -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) {
@@ -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
@@ -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 ----------------------------- */