49
49
#include " global.h"
50
50
#include " plgdbsem.h"
51
51
#include " filamdbf.h"
52
+ #include " filamzip.h"
52
53
#include " tabdos.h"
53
54
#include " valblk.h"
54
55
#define NO_FUNC
@@ -139,7 +140,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
139
140
if (fread (buf, HEADLEN, 1 , file) != 1 ) {
140
141
strcpy (g->Message , MSG (NO_READ_32));
141
142
return RC_NF;
142
- } // endif fread
143
+ } // endif fread
143
144
144
145
// Check first byte to be sure of .dbf type
145
146
if ((buf->Version & 0x03 ) != DBFTYPE) {
@@ -149,7 +150,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
149
150
if ((buf->Version & 0x30 ) == 0x30 ) {
150
151
strcpy (g->Message , MSG (FOXPRO_FILE));
151
152
dbc = 264 ; // FoxPro database container
152
- } // endif Version
153
+ } // endif Version
153
154
154
155
} else
155
156
strcpy (g->Message , MSG (DBASE_FILE));
@@ -158,12 +159,12 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
158
159
if (fseek (file, buf->Headlen () - dbc, SEEK_SET) != 0 ) {
159
160
sprintf (g->Message , MSG (BAD_HEADER), fn);
160
161
return RC_FX;
161
- } // endif fseek
162
+ } // endif fseek
162
163
163
164
if (fread (&endmark, 2 , 1 , file) != 1 ) {
164
165
strcpy (g->Message , MSG (BAD_HEAD_END));
165
166
return RC_FX;
166
- } // endif fread
167
+ } // endif fread
167
168
168
169
// Some files have just 1D others have 1D00 following fields
169
170
if (endmark[0 ] != EOH && endmark[1 ] != EOH) {
@@ -172,21 +173,66 @@ static int dbfhead(PGLOBAL g, FILE *file, PCSZ fn, DBFHEADER *buf)
172
173
if (rc == RC_OK)
173
174
return RC_FX;
174
175
175
- } // endif endmark
176
+ } // endif endmark
176
177
177
178
// Calculate here the number of fields while we have the dbc info
178
179
buf->SetFields ((buf->Headlen () - dbc - 1 ) / 32 );
179
180
fseek (file, HEADLEN, SEEK_SET);
180
181
return rc;
181
182
} // end of dbfhead
182
183
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
+
183
229
/* -------------------------- Function DBFColumns ------------------------- */
184
230
185
231
/* ***************************************************************************/
186
232
/* DBFColumns: constructs the result blocks containing the description */
187
233
/* of all the columns of a DBF file that will be retrieved by #GetData. */
188
234
/* ***************************************************************************/
189
- PQRYRES DBFColumns (PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
235
+ PQRYRES DBFColumns (PGLOBAL g, PCSZ dp, PCSZ fn, PTOS topt, bool info)
190
236
{
191
237
int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
192
238
TYPE_INT, TYPE_INT, TYPE_SHORT};
@@ -196,10 +242,12 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
196
242
char buf[2 ], filename[_MAX_PATH];
197
243
int ncol = sizeof (buftyp) / sizeof (int );
198
244
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 ;
203
251
PQRYRES qrp;
204
252
PCOLRES crp;
205
253
@@ -217,21 +265,55 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
217
265
/* ***********************************************************************/
218
266
PlugSetPath (filename, fn, dp);
219
267
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 ();
235
317
} else
236
318
fields = 0 ;
237
319
@@ -241,19 +323,21 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
241
323
if (info || !qrp) {
242
324
if (infile)
243
325
fclose (infile);
326
+ else if (zutp)
327
+ zutp->close ();
244
328
245
329
return qrp;
246
- } // endif info
330
+ } // endif info
247
331
248
332
if (trace (1 )) {
249
333
htrc (" Structure of %s\n " , filename);
250
334
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 );
254
338
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 );
257
341
htrc (" Field Type Offset Len Dec Set Mdx\n " );
258
342
} // endif trace
259
343
@@ -265,21 +349,24 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
265
349
for (field = 0 ; field < fields; field++) {
266
350
bad = FALSE ;
267
351
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 ) {
269
355
sprintf (g->Message , MSG (ERR_READING_REC), field+1 , fn);
270
356
goto err;
271
- } else
272
- len = thisfield.Length ;
357
+ } // endif fread
358
+
359
+ len = tfp->Length ;
273
360
274
361
if (trace (1 ))
275
362
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 );
278
365
279
366
/* ***********************************************************************/
280
367
/* Now get the results into blocks. */
281
368
/* ***********************************************************************/
282
- switch (thisfield. Type ) {
369
+ switch (tfp-> Type ) {
283
370
case ' C' : // Characters
284
371
case ' L' : // Logical 'T' or 'F' or space
285
372
type = TYPE_STRING;
@@ -294,7 +381,7 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
294
381
// type = TYPE_INT;
295
382
// break;
296
383
case ' N' :
297
- type = (thisfield. Decimals ) ? TYPE_DOUBLE
384
+ type = (tfp-> Decimals ) ? TYPE_DOUBLE
298
385
: (len > 10 ) ? TYPE_BIGINT : TYPE_INT;
299
386
break ;
300
387
case ' F' : // Float
@@ -306,8 +393,8 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
306
393
break ;
307
394
default :
308
395
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 );
311
398
goto err;
312
399
} // endif info
313
400
@@ -316,27 +403,31 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
316
403
} // endswitch Type
317
404
318
405
crp = qrp->Colresp ; // Column Name
319
- crp->Kdata ->SetValue (thisfield. Name , field);
406
+ crp->Kdata ->SetValue (tfp-> Name , field);
320
407
crp = crp->Next ; // Data Type
321
408
crp->Kdata ->SetValue ((int )type, field);
322
409
crp = crp->Next ; // Type Name
323
410
324
411
if (bad) {
325
- buf[0 ] = thisfield. Type ;
412
+ buf[0 ] = tfp-> Type ;
326
413
crp->Kdata ->SetValue (buf, field);
327
414
} else
328
415
crp->Kdata ->SetValue (GetTypeName (type), field);
329
416
330
417
crp = crp->Next ; // Precision
331
- crp->Kdata ->SetValue ((int )thisfield. Length , field);
418
+ crp->Kdata ->SetValue ((int )tfp-> Length , field);
332
419
crp = crp->Next ; // Length
333
- crp->Kdata ->SetValue ((int )thisfield. Length , field);
420
+ crp->Kdata ->SetValue ((int )tfp-> Length , field);
334
421
crp = crp->Next ; // Scale (precision)
335
- crp->Kdata ->SetValue ((int )thisfield. Decimals , field);
422
+ crp->Kdata ->SetValue ((int )tfp-> Decimals , field);
336
423
} // endfor field
337
424
338
425
qrp->Nblin = field;
339
- fclose (infile);
426
+
427
+ if (infile)
428
+ fclose (infile);
429
+ else if (zutp)
430
+ zutp->close ();
340
431
341
432
#if 0
342
433
if (info) {
@@ -347,9 +438,9 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
347
438
348
439
sprintf(buf,
349
440
"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]);
353
444
354
445
strcat(g->Message, buf);
355
446
} // endif info
@@ -360,9 +451,13 @@ PQRYRES DBFColumns(PGLOBAL g, PCSZ dp, PCSZ fn, bool info)
360
451
/* *************************************************************************/
361
452
return qrp;
362
453
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 ;
366
461
} // end of DBFColumns
367
462
368
463
/* ---------------------------- Class DBFBASE ----------------------------- */
0 commit comments