~ubuntu-branches/ubuntu/hardy/php5/hardy-updates

« back to all changes in this revision

Viewing changes to ext/dbase/dbase.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-10-09 03:14:32 UTC
  • Revision ID: james.westby@ubuntu.com-20051009031432-kspik3lobxstafv9
Tags: upstream-5.0.5
ImportĀ upstreamĀ versionĀ 5.0.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   +----------------------------------------------------------------------+
 
3
   | PHP Version 5                                                        |
 
4
   +----------------------------------------------------------------------+
 
5
   | Copyright (c) 1997-2004 The PHP Group                                |
 
6
   +----------------------------------------------------------------------+
 
7
   | This source file is subject to version 3.0 of the PHP license,       |
 
8
   | that is bundled with this package in the file LICENSE, and is        |
 
9
   | available through the world-wide-web at the following url:           |
 
10
   | http://www.php.net/license/3_0.txt.                                  |
 
11
   | If you did not receive a copy of the PHP license and are unable to   |
 
12
   | obtain it through the world-wide-web, please send a note to          |
 
13
   | license@php.net so we can mail you a copy immediately.               |
 
14
   +----------------------------------------------------------------------+
 
15
   | Author: Jim Winstead <jimw@php.net>                                  |
 
16
   +----------------------------------------------------------------------+
 
17
 */
 
18
 
 
19
/* $Id: dbase.c,v 1.72.2.1 2005/02/04 14:29:05 derick Exp $ */
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
#include "config.h"
 
23
#endif
 
24
 
 
25
#include "php.h"
 
26
#include "safe_mode.h"
 
27
#include "fopen_wrappers.h"
 
28
#include "php_globals.h"
 
29
 
 
30
#include <stdlib.h>
 
31
 
 
32
#ifdef HAVE_SYS_TYPES_H
 
33
#include <sys/types.h>
 
34
#endif
 
35
 
 
36
#if DBASE
 
37
#include "php_dbase.h"
 
38
#include "dbf.h"
 
39
#if defined(THREAD_SAFE)
 
40
DWORD DbaseTls;
 
41
static int numthreads=0;
 
42
void *dbase_mutex;
 
43
 
 
44
typedef struct dbase_global_struct{
 
45
        int le_dbhead;
 
46
}dbase_global_struct;
 
47
 
 
48
#define DBase_GLOBAL(a) dbase_globals->a
 
49
 
 
50
#define DBase_TLS_VARS \
 
51
        dbase_global_struct *dbase_globals; \
 
52
        dbase_globals=TlsGetValue(DbaseTls); 
 
53
 
 
54
#else
 
55
static int le_dbhead;
 
56
#define DBase_GLOBAL(a) a
 
57
#define DBase_TLS_VARS
 
58
#endif
 
59
 
 
60
#include <fcntl.h>
 
61
#include <errno.h>
 
62
 
 
63
 
 
64
static void _close_dbase(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 
65
{
 
66
        dbhead_t *dbhead = (dbhead_t *)rsrc->ptr;
 
67
 
 
68
        close(dbhead->db_fd);
 
69
        free_dbf_head(dbhead);
 
70
}
 
71
 
 
72
 
 
73
PHP_MINIT_FUNCTION(dbase)
 
74
{
 
75
#if defined(THREAD_SAFE)
 
76
        dbase_global_struct *dbase_globals;
 
77
#ifdef COMPILE_DL_DBASE
 
78
        CREATE_MUTEX(dbase_mutex, "DBase_TLS");
 
79
        SET_MUTEX(dbase_mutex);
 
80
        numthreads++;
 
81
        if (numthreads==1){
 
82
        if ((DbaseTls=TlsAlloc())==0xFFFFFFFF){
 
83
                FREE_MUTEX(dbase_mutex);
 
84
                return 0;
 
85
        }}
 
86
        FREE_MUTEX(dbase_mutex);
 
87
#endif
 
88
        dbase_globals = (dbase_global_struct *) LocalAlloc(LPTR, sizeof(dbase_global_struct)); 
 
89
        TlsSetValue(DbaseTls, (void *) dbase_globals);
 
90
#endif
 
91
        DBase_GLOBAL(le_dbhead) =
 
92
                zend_register_list_destructors_ex(_close_dbase, NULL, "dbase", module_number);
 
93
        return SUCCESS;
 
94
}
 
95
 
 
96
static PHP_MSHUTDOWN_FUNCTION(dbase)
 
97
{
 
98
#if defined(THREAD_SAFE)
 
99
        dbase_global_struct *dbase_globals;
 
100
        dbase_globals = TlsGetValue(DbaseTls); 
 
101
        if (dbase_globals != 0) 
 
102
                LocalFree((HLOCAL) dbase_globals); 
 
103
#ifdef COMPILE_DL_DBASE
 
104
        SET_MUTEX(dbase_mutex);
 
105
        numthreads--;
 
106
        if (!numthreads){
 
107
        if (!TlsFree(DbaseTls)){
 
108
                FREE_MUTEX(dbase_mutex);
 
109
                return 0;
 
110
        }}
 
111
        FREE_MUTEX(dbase_mutex);
 
112
#endif
 
113
#endif
 
114
        return SUCCESS;
 
115
}
 
116
 
 
117
/* {{{ proto int dbase_open(string name, int mode)
 
118
   Opens a dBase-format database file */
 
119
PHP_FUNCTION(dbase_open)
 
120
{
 
121
        zval **dbf_name, **options;
 
122
        dbhead_t *dbh;
 
123
        int handle;
 
124
        DBase_TLS_VARS;
 
125
 
 
126
        if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &dbf_name, &options) == FAILURE) {
 
127
                WRONG_PARAM_COUNT;
 
128
        }
 
129
        convert_to_string_ex(dbf_name);
 
130
        convert_to_long_ex(options);
 
131
 
 
132
        if (Z_LVAL_PP(options) == 1) {
 
133
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot open %s in write-only mode", Z_STRVAL_PP(dbf_name));
 
134
                RETURN_FALSE;
 
135
        }
 
136
 
 
137
        if (PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(dbf_name), NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
 
138
                RETURN_FALSE;
 
139
        }
 
140
        
 
141
        if (php_check_open_basedir(Z_STRVAL_PP(dbf_name) TSRMLS_CC)) {
 
142
                RETURN_FALSE;
 
143
        }
 
144
 
 
145
        dbh = dbf_open(Z_STRVAL_PP(dbf_name), Z_LVAL_PP(options) TSRMLS_CC);
 
146
        if (dbh == NULL) {
 
147
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to open database %s", Z_STRVAL_PP(dbf_name));
 
148
                RETURN_FALSE;
 
149
        }
 
150
 
 
151
        handle = zend_list_insert(dbh, DBase_GLOBAL(le_dbhead));
 
152
        RETURN_LONG(handle);
 
153
}
 
154
/* }}} */
 
155
 
 
156
/* {{{ proto bool dbase_close(int identifier)
 
157
   Closes an open dBase-format database file */
 
158
PHP_FUNCTION(dbase_close)
 
159
{
 
160
        zval **dbh_id;
 
161
        dbhead_t *dbh;
 
162
        int dbh_type;
 
163
        DBase_TLS_VARS;
 
164
 
 
165
        if (ZEND_NUM_ARGS() != 1 || (zend_get_parameters_ex(1, &dbh_id) == FAILURE)) {
 
166
                WRONG_PARAM_COUNT;
 
167
        }
 
168
        convert_to_long_ex(dbh_id);
 
169
        dbh = zend_list_find(Z_LVAL_PP(dbh_id), &dbh_type);
 
170
        if (!dbh || dbh_type != DBase_GLOBAL(le_dbhead)) {
 
171
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find database for identifier %ld", Z_LVAL_PP(dbh_id));
 
172
                RETURN_FALSE;
 
173
        }
 
174
 
 
175
        zend_list_delete(Z_LVAL_PP(dbh_id));
 
176
        RETURN_TRUE;
 
177
}
 
178
/* }}} */
 
179
 
 
180
/* {{{ proto int dbase_numrecords(int identifier)
 
181
   Returns the number of records in the database */
 
182
PHP_FUNCTION(dbase_numrecords)
 
183
{
 
184
        zval **dbh_id;
 
185
        dbhead_t *dbh;
 
186
        int dbh_type;
 
187
        DBase_TLS_VARS;
 
188
 
 
189
        if (ZEND_NUM_ARGS() != 1 || (zend_get_parameters_ex(1, &dbh_id) == FAILURE)) {
 
190
                WRONG_PARAM_COUNT;
 
191
        }
 
192
        convert_to_long_ex(dbh_id);
 
193
        dbh = zend_list_find(Z_LVAL_PP(dbh_id), &dbh_type);
 
194
        if (!dbh || dbh_type != DBase_GLOBAL(le_dbhead)) {
 
195
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find database for identifier %ld", Z_LVAL_PP(dbh_id));
 
196
                RETURN_FALSE;
 
197
        }
 
198
 
 
199
        RETURN_LONG(dbh->db_records);
 
200
}
 
201
/* }}} */
 
202
 
 
203
/* {{{ proto int dbase_numfields(int identifier)
 
204
   Returns the number of fields (columns) in the database */
 
205
PHP_FUNCTION(dbase_numfields)
 
206
{
 
207
        zval **dbh_id;
 
208
        dbhead_t *dbh;
 
209
        int dbh_type;
 
210
        DBase_TLS_VARS;
 
211
 
 
212
        if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &dbh_id) == FAILURE) {
 
213
                WRONG_PARAM_COUNT;
 
214
        }
 
215
        convert_to_long_ex(dbh_id);
 
216
        dbh = zend_list_find(Z_LVAL_PP(dbh_id), &dbh_type);
 
217
        if (!dbh || dbh_type != DBase_GLOBAL(le_dbhead)) {
 
218
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find database for identifier %ld", Z_LVAL_PP(dbh_id));
 
219
                RETURN_FALSE;
 
220
        }
 
221
 
 
222
        RETURN_LONG(dbh->db_nfields);
 
223
}
 
224
/* }}} */
 
225
 
 
226
/* {{{ proto bool dbase_pack(int identifier)
 
227
   Packs the database (deletes records marked for deletion) */
 
228
PHP_FUNCTION(dbase_pack)
 
229
{
 
230
        zval **dbh_id;
 
231
        dbhead_t *dbh;
 
232
        int dbh_type;
 
233
        DBase_TLS_VARS;
 
234
 
 
235
        if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &dbh_id) == FAILURE) {
 
236
                WRONG_PARAM_COUNT;
 
237
        }
 
238
        convert_to_long_ex(dbh_id);
 
239
        dbh = zend_list_find(Z_LVAL_PP(dbh_id), &dbh_type);
 
240
        if (!dbh || dbh_type != DBase_GLOBAL(le_dbhead)) {
 
241
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find database for identifier %ld", Z_LVAL_PP(dbh_id));
 
242
                RETURN_FALSE;
 
243
        }
 
244
 
 
245
        pack_dbf(dbh);
 
246
        put_dbf_info(dbh);
 
247
        RETURN_TRUE;
 
248
}
 
249
/* }}} */
 
250
 
 
251
/* {{{ proto bool dbase_add_record(int identifier, array data)
 
252
   Adds a record to the database */
 
253
PHP_FUNCTION(dbase_add_record)
 
254
{
 
255
        zval **dbh_id, **fields, **field;
 
256
        dbhead_t *dbh;
 
257
        int dbh_type;
 
258
 
 
259
        int num_fields;
 
260
        dbfield_t *dbf, *cur_f;
 
261
        char *cp, *t_cp;
 
262
        int i;
 
263
        DBase_TLS_VARS;
 
264
 
 
265
        if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &dbh_id, &fields) == FAILURE) {
 
266
                WRONG_PARAM_COUNT;
 
267
        }
 
268
        convert_to_long_ex(dbh_id);
 
269
        if (Z_TYPE_PP(fields) != IS_ARRAY) {
 
270
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected array as second parameter");
 
271
                RETURN_FALSE;
 
272
        }
 
273
 
 
274
        dbh = zend_list_find(Z_LVAL_PP(dbh_id), &dbh_type);
 
275
        if (!dbh || dbh_type != DBase_GLOBAL(le_dbhead)) {
 
276
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find database for identifier %ld", Z_LVAL_PP(dbh_id));
 
277
                RETURN_FALSE;
 
278
        }
 
279
 
 
280
        num_fields = zend_hash_num_elements(Z_ARRVAL_PP(fields));
 
281
 
 
282
        if (num_fields != dbh->db_nfields) {
 
283
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Wrong number of fields specified");
 
284
                RETURN_FALSE;
 
285
        }
 
286
 
 
287
        cp = t_cp = (char *)emalloc(dbh->db_rlen + 1);
 
288
        *t_cp++ = VALID_RECORD;
 
289
 
 
290
        dbf = dbh->db_fields;
 
291
        for (i = 0, cur_f = dbf; cur_f < &dbf[num_fields]; i++, cur_f++) {
 
292
                zval tmp;
 
293
                if (zend_hash_index_find(Z_ARRVAL_PP(fields), i, (void **)&field) == FAILURE) {
 
294
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "unexpected error");
 
295
                        efree(cp);
 
296
                        RETURN_FALSE;
 
297
                }
 
298
                
 
299
                tmp = **field;
 
300
                zval_copy_ctor(&tmp);
 
301
                convert_to_string(&tmp);
 
302
                snprintf(t_cp, cur_f->db_flen+1, cur_f->db_format, Z_STRVAL(tmp));
 
303
                zval_dtor(&tmp); 
 
304
                t_cp += cur_f->db_flen;
 
305
        }
 
306
 
 
307
        dbh->db_records++;
 
308
        if (put_dbf_record(dbh, dbh->db_records, cp) < 0) {
 
309
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to put record at %ld", dbh->db_records);
 
310
                efree(cp);
 
311
                RETURN_FALSE;
 
312
        }
 
313
 
 
314
        put_dbf_info(dbh);
 
315
        efree(cp);
 
316
 
 
317
        RETURN_TRUE;
 
318
}
 
319
/* }}} */
 
320
 
 
321
/* {{{ proto bool dbase_replace_record(int identifier, array data, int recnum)
 
322
   Replaces a record to the database */
 
323
PHP_FUNCTION(dbase_replace_record)
 
324
{
 
325
        zval **dbh_id, **fields, **field, **recnum;
 
326
        dbhead_t *dbh;
 
327
        int dbh_type;
 
328
 
 
329
        int num_fields;
 
330
        dbfield_t *dbf, *cur_f;
 
331
        char *cp, *t_cp;
 
332
        int i;
 
333
        DBase_TLS_VARS;
 
334
 
 
335
        if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &dbh_id, &fields, &recnum) == FAILURE) {
 
336
                WRONG_PARAM_COUNT;
 
337
        }
 
338
        convert_to_long_ex(dbh_id);
 
339
        convert_to_long_ex(recnum);
 
340
        if (Z_TYPE_PP(fields) != IS_ARRAY) {
 
341
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected array as second parameter");
 
342
                RETURN_FALSE;
 
343
        }
 
344
 
 
345
        dbh = zend_list_find(Z_LVAL_PP(dbh_id), &dbh_type);
 
346
        if (!dbh || dbh_type != DBase_GLOBAL(le_dbhead)) {
 
347
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find database for identifier %ld", Z_LVAL_PP(dbh_id));
 
348
                RETURN_FALSE;
 
349
        }
 
350
 
 
351
        num_fields = zend_hash_num_elements(Z_ARRVAL_PP(fields));
 
352
 
 
353
        if (num_fields != dbh->db_nfields) {
 
354
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Wrong number of fields specified");
 
355
                RETURN_FALSE;
 
356
        }
 
357
 
 
358
        cp = t_cp = (char *)emalloc(dbh->db_rlen + 1);
 
359
        *t_cp++ = VALID_RECORD;
 
360
 
 
361
        dbf = dbh->db_fields;
 
362
        for (i = 0, cur_f = dbf; cur_f < &dbf[num_fields]; i++, cur_f++) {
 
363
                if (zend_hash_index_find(Z_ARRVAL_PP(fields), i, (void **)&field) == FAILURE) {
 
364
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "unexpected error");
 
365
                        efree(cp);
 
366
                        RETURN_FALSE;
 
367
                }
 
368
                convert_to_string_ex(field);
 
369
                snprintf(t_cp, cur_f->db_flen+1, cur_f->db_format, Z_STRVAL_PP(field)); 
 
370
                t_cp += cur_f->db_flen;
 
371
        }
 
372
 
 
373
        if (put_dbf_record(dbh, Z_LVAL_PP(recnum), cp) < 0) {
 
374
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to put record at %ld", dbh->db_records);
 
375
                efree(cp);
 
376
                RETURN_FALSE;
 
377
        }
 
378
 
 
379
        put_dbf_info(dbh);
 
380
        efree(cp);
 
381
 
 
382
        RETURN_TRUE;
 
383
}
 
384
/* }}} */
 
385
 
 
386
/* {{{ proto bool dbase_delete_record(int identifier, int record)
 
387
   Marks a record to be deleted */
 
388
PHP_FUNCTION(dbase_delete_record)
 
389
{
 
390
        zval **dbh_id, **record;
 
391
        dbhead_t *dbh;
 
392
        int dbh_type;
 
393
        DBase_TLS_VARS;
 
394
 
 
395
        if (ZEND_NUM_ARGS() != 2 || (zend_get_parameters_ex(2, &dbh_id, &record) == FAILURE)) {
 
396
                WRONG_PARAM_COUNT;
 
397
        }
 
398
        convert_to_long_ex(dbh_id);
 
399
        convert_to_long_ex(record);
 
400
 
 
401
        dbh = zend_list_find(Z_LVAL_PP(dbh_id), &dbh_type);
 
402
        if (!dbh || dbh_type != DBase_GLOBAL(le_dbhead)) {
 
403
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find database for identifier %ld", Z_LVAL_PP(dbh_id));
 
404
                RETURN_FALSE;
 
405
        }
 
406
 
 
407
        if (del_dbf_record(dbh, Z_LVAL_PP(record)) < 0) {
 
408
                if (Z_LVAL_PP(record) > dbh->db_records) {
 
409
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "record %ld out of bounds", Z_LVAL_PP(record));
 
410
                } else {
 
411
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to delete record %ld", Z_LVAL_PP(record));
 
412
                }
 
413
                RETURN_FALSE;
 
414
        }
 
415
 
 
416
        put_dbf_info(dbh);
 
417
        RETURN_TRUE;
 
418
}
 
419
/* }}} */
 
420
 
 
421
/* {{{ php_dbase_get_record
 
422
 */  
 
423
static void php_dbase_get_record(INTERNAL_FUNCTION_PARAMETERS, int assoc)
 
424
{
 
425
        zval **dbh_id, **record;
 
426
        dbhead_t *dbh;
 
427
        int dbh_type;
 
428
        dbfield_t *dbf, *cur_f;
 
429
        char *data, *fnp, *str_value;
 
430
        size_t cursize = 0;
 
431
        long overflow_test;
 
432
        int errno_save;
 
433
        DBase_TLS_VARS;
 
434
 
 
435
        if (ZEND_NUM_ARGS() != 2 || (zend_get_parameters_ex(2, &dbh_id, &record) == FAILURE)) {
 
436
                WRONG_PARAM_COUNT;
 
437
        }
 
438
        convert_to_long_ex(dbh_id);
 
439
        convert_to_long_ex(record);
 
440
 
 
441
        dbh = zend_list_find(Z_LVAL_PP(dbh_id), &dbh_type);
 
442
        if (!dbh || dbh_type != DBase_GLOBAL(le_dbhead)) {
 
443
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find database for identifier %ld", Z_LVAL_PP(dbh_id));
 
444
                RETURN_FALSE;
 
445
        }
 
446
 
 
447
        if ((data = get_dbf_record(dbh, Z_LVAL_PP(record))) == NULL) {
 
448
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to read bad record %ld", Z_LVAL_PP(record));
 
449
                RETURN_FALSE;
 
450
        }
 
451
 
 
452
        dbf = dbh->db_fields;
 
453
 
 
454
        array_init(return_value);
 
455
 
 
456
        fnp = NULL;
 
457
        for (cur_f = dbf; cur_f < &dbf[dbh->db_nfields]; cur_f++) {
 
458
                /* get the value */
 
459
                str_value = (char *)emalloc(cur_f->db_flen + 1);
 
460
 
 
461
                if(cursize <= (unsigned)cur_f->db_flen) {
 
462
                        cursize = cur_f->db_flen + 1;
 
463
                        fnp = erealloc(fnp, cursize);
 
464
                }
 
465
                snprintf(str_value, cursize, cur_f->db_format, get_field_val(data, cur_f, fnp));
 
466
 
 
467
                /* now convert it to the right php internal type */
 
468
                switch (cur_f->db_type) {
 
469
                        case 'C':
 
470
                        case 'D':
 
471
                                if (!assoc) {
 
472
                                        add_next_index_string(return_value, str_value, 1);
 
473
                                } else {
 
474
                                        add_assoc_string(return_value, cur_f->db_fname, str_value, 1);
 
475
                                }
 
476
                                break;
 
477
                        case 'I':       /* FALLS THROUGH */
 
478
                        case 'N':
 
479
                                if (cur_f->db_fdc == 0) {
 
480
                                        /* Large integers in dbase can be larger than long */
 
481
                                        errno_save = errno;
 
482
                                        overflow_test = strtol(str_value, NULL, 10);
 
483
                                        if (errno == ERANGE) {
 
484
                                            /* If the integer is too large, keep it as string */
 
485
                                                if (!assoc) {
 
486
                                                    add_next_index_string(return_value, str_value, 1);
 
487
                                                } else {
 
488
                                                    add_assoc_string(return_value, cur_f->db_fname, str_value, 1);
 
489
                                                }
 
490
                                        } else {
 
491
                                                if (!assoc) {
 
492
                                                    add_next_index_long(return_value, overflow_test);
 
493
                                                } else {
 
494
                                                    add_assoc_long(return_value, cur_f->db_fname, overflow_test);
 
495
                                                }
 
496
                                        }
 
497
                                        errno = errno_save;
 
498
                                } else {
 
499
                                        if (!assoc) {
 
500
                                                add_next_index_double(return_value, atof(str_value));
 
501
                                        } else {
 
502
                                                add_assoc_double(return_value, cur_f->db_fname, atof(str_value));
 
503
                                        }
 
504
                                }
 
505
                                break;
 
506
                        case 'L':       /* we used to FALL THROUGH, but now we check for T/Y and F/N
 
507
                                                   and insert 1 or 0, respectively.  db_fdc is the number of
 
508
                                                   decimals, which we don't care about.      3/14/2001 LEW */
 
509
                                if ((*str_value == 'T') || (*str_value == 'Y')) {
 
510
                                        if (!assoc) {
 
511
                                                add_next_index_long(return_value, strtol("1", NULL, 10));
 
512
                                        } else {
 
513
                                                add_assoc_long(return_value, cur_f->db_fname,strtol("1", NULL, 10));
 
514
                                        }
 
515
                                } else {
 
516
                                        if ((*str_value == 'F') || (*str_value == 'N')) {
 
517
                                                if (!assoc) {
 
518
                                                        add_next_index_long(return_value, strtol("0", NULL, 10));
 
519
                                                } else {
 
520
                                                        add_assoc_long(return_value, cur_f->db_fname,strtol("0", NULL, 10));
 
521
                                                }
 
522
                                        } else {
 
523
                                                if (!assoc) {
 
524
                                                        add_next_index_long(return_value, strtol(" ", NULL, 10));
 
525
                                                } else {
 
526
                                                        add_assoc_long(return_value, cur_f->db_fname,strtol(" ", NULL, 10));
 
527
                                                }
 
528
                                        }
 
529
                                }
 
530
                                break;
 
531
                        case 'M':
 
532
                                /* this is a memo field. don't know how to deal with this yet */
 
533
                                break;
 
534
                        default:
 
535
                                /* should deal with this in some way */
 
536
                                break;
 
537
                }
 
538
                efree(str_value);
 
539
        }
 
540
 
 
541
        efree(fnp);
 
542
 
 
543
        /* mark whether this record was deleted */
 
544
        if (data[0] == '*') {
 
545
                add_assoc_long(return_value, "deleted", 1);
 
546
        } else {
 
547
                add_assoc_long(return_value, "deleted", 0);
 
548
        }
 
549
 
 
550
        free(data);
 
551
}
 
552
/* }}} */
 
553
 
 
554
/* {{{ proto array dbase_get_record(int identifier, int record)
 
555
   Returns an array representing a record from the database */
 
556
PHP_FUNCTION(dbase_get_record)
 
557
{
 
558
        php_dbase_get_record(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
 
559
}
 
560
/* }}} */
 
561
 
 
562
/* From Martin Kuba <makub@aida.inet.cz> */
 
563
/* {{{ proto array dbase_get_record_with_names(int identifier, int record)
 
564
   Returns an associative array representing a record from the database */
 
565
PHP_FUNCTION(dbase_get_record_with_names)
 
566
{
 
567
        php_dbase_get_record(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
 
568
}
 
569
/* }}} */
 
570
 
 
571
/* {{{ proto bool dbase_create(string filename, array fields)
 
572
   Creates a new dBase-format database file */
 
573
PHP_FUNCTION(dbase_create)
 
574
{
 
575
        zval **filename, **fields, **field, **value;
 
576
        int fd;
 
577
        dbhead_t *dbh;
 
578
 
 
579
        int num_fields;
 
580
        dbfield_t *dbf, *cur_f;
 
581
        int i, rlen, handle;
 
582
        DBase_TLS_VARS;
 
583
 
 
584
        if (ZEND_NUM_ARGS() != 2 || (zend_get_parameters_ex(2, &filename, &fields) == FAILURE)) {
 
585
                WRONG_PARAM_COUNT;
 
586
        }
 
587
        convert_to_string_ex(filename);
 
588
 
 
589
        if (Z_TYPE_PP(fields) != IS_ARRAY) {
 
590
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected array as second parameter");
 
591
                RETURN_FALSE;
 
592
        }
 
593
 
 
594
        if (PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(filename), NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
 
595
                RETURN_FALSE;
 
596
        }
 
597
        
 
598
        if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) {
 
599
                RETURN_FALSE;
 
600
        }
 
601
 
 
602
        if ((fd = VCWD_OPEN_MODE(Z_STRVAL_PP(filename), O_BINARY|O_RDWR|O_CREAT, 0644)) < 0) {
 
603
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create database (%d): %s", errno, strerror(errno));
 
604
                RETURN_FALSE;
 
605
        }
 
606
 
 
607
        num_fields = zend_hash_num_elements(Z_ARRVAL_PP(fields));
 
608
 
 
609
        /* have to use regular malloc() because this gets free()d by
 
610
           code in the dbase library */
 
611
        dbh = (dbhead_t *)malloc(sizeof(dbhead_t));
 
612
        dbf = (dbfield_t *)malloc(sizeof(dbfield_t) * num_fields);
 
613
        if (!dbh || !dbf) {
 
614
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to allocate memory for header info");
 
615
                RETURN_FALSE;
 
616
        }
 
617
        
 
618
        /* initialize the header structure */
 
619
        dbh->db_fields = dbf;
 
620
        dbh->db_fd = fd;
 
621
        dbh->db_dbt = DBH_TYPE_NORMAL;
 
622
        strcpy(dbh->db_date, "19930818");
 
623
        dbh->db_records = 0;
 
624
        dbh->db_nfields = num_fields;
 
625
        dbh->db_hlen = sizeof(struct dbf_dhead) + 1 + num_fields * sizeof(struct dbf_dfield);
 
626
 
 
627
        rlen = 1;
 
628
        /**
 
629
         * Patch by greg@darkphoton.com
 
630
         **/
 
631
        /* make sure that the db_format entries for all fields are set to NULL to ensure we
 
632
       don't seg fault if there's an error and we need to call free_dbf_head() before all
 
633
       fields have been defined. */
 
634
        for (i = 0, cur_f = dbf; i < num_fields; i++, cur_f++) {
 
635
                cur_f->db_format = NULL;
 
636
        }
 
637
        /**
 
638
         * end patch
 
639
         */
 
640
 
 
641
 
 
642
        for (i = 0, cur_f = dbf; i < num_fields; i++, cur_f++) {
 
643
                /* look up the first field */
 
644
                if (zend_hash_index_find(Z_ARRVAL_PP(fields), i, (void **)&field) == FAILURE) {
 
645
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to find field %d", i);
 
646
                        free_dbf_head(dbh);
 
647
                        RETURN_FALSE;
 
648
                }
 
649
 
 
650
                if (Z_TYPE_PP (field) != IS_ARRAY) {
 
651
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "second parameter must be array of arrays");
 
652
                        free_dbf_head(dbh);
 
653
                        RETURN_FALSE;
 
654
                }
 
655
 
 
656
                /* field name */
 
657
                if (zend_hash_index_find(Z_ARRVAL_PP(field), 0, (void **)&value) == FAILURE) {
 
658
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "expected field name as first element of list in field %d", i);
 
659
                        free_dbf_head(dbh);
 
660
                        RETURN_FALSE;
 
661
                }
 
662
                convert_to_string_ex(value);
 
663
                if (Z_STRLEN_PP(value) > 10 || Z_STRLEN_PP(value) == 0) {
 
664
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid field name '%s' (must be non-empty and less than or equal to 10 characters)", Z_STRVAL_PP(value));
 
665
                        free_dbf_head(dbh);
 
666
                        RETURN_FALSE;
 
667
                }
 
668
                copy_crimp(cur_f->db_fname, Z_STRVAL_PP(value), Z_STRLEN_PP(value));
 
669
 
 
670
                /* field type */
 
671
                if (zend_hash_index_find(Z_ARRVAL_PP (field), 1, (void **)&value) == FAILURE) {
 
672
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "expected field type as second element of list in field %d", i);
 
673
                        RETURN_FALSE;
 
674
                }
 
675
                convert_to_string_ex(value);
 
676
                cur_f->db_type = toupper(*Z_STRVAL_PP(value));
 
677
 
 
678
                cur_f->db_fdc = 0;
 
679
 
 
680
                /* verify the field length */
 
681
                switch (cur_f->db_type) {
 
682
                case 'L':
 
683
                        cur_f->db_flen = 1;
 
684
                        break;
 
685
                case 'M':
 
686
                        cur_f->db_flen = 10;
 
687
                        dbh->db_dbt = DBH_TYPE_MEMO;
 
688
                        /* should create the memo file here, probably */
 
689
                        break;
 
690
                case 'D':
 
691
                        cur_f->db_flen = 8;
 
692
                        break;
 
693
                case 'N':
 
694
                case 'C':
 
695
                        /* field length */
 
696
                        if (zend_hash_index_find(Z_ARRVAL_PP (field), 2, (void **)&value) == FAILURE) {
 
697
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "expected field length as third element of list in field %d", i);
 
698
                                free_dbf_head(dbh);
 
699
                                RETURN_FALSE;
 
700
                        }
 
701
                        convert_to_long_ex(value);
 
702
                        cur_f->db_flen = Z_LVAL_PP(value);
 
703
 
 
704
                        if (cur_f->db_type == 'N') {
 
705
                                if (zend_hash_index_find(Z_ARRVAL_PP (field), 3, (void **)&value) == FAILURE) {
 
706
                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "expected field precision as fourth element of list in field %d", i);
 
707
                                        free_dbf_head(dbh);
 
708
                                        RETURN_FALSE;
 
709
                                }
 
710
                                convert_to_long_ex(value);
 
711
                                cur_f->db_fdc = Z_LVAL_PP(value);
 
712
                        }
 
713
                        break;
 
714
                default:
 
715
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown field type '%c'", cur_f->db_type);
 
716
                }
 
717
                cur_f->db_foffset = rlen;
 
718
                rlen += cur_f->db_flen;
 
719
        
 
720
                cur_f->db_format = get_dbf_f_fmt(cur_f);
 
721
        }
 
722
 
 
723
        dbh->db_rlen = rlen;
 
724
        put_dbf_info(dbh);
 
725
 
 
726
        handle = zend_list_insert(dbh, DBase_GLOBAL(le_dbhead));
 
727
        RETURN_LONG(handle);
 
728
}
 
729
/* }}} */
 
730
 
 
731
/* {{{ dbase_functions[]
 
732
 */
 
733
function_entry dbase_functions[] = {
 
734
        PHP_FE(dbase_open,                                                              NULL)
 
735
        PHP_FE(dbase_create,                                                    NULL)
 
736
        PHP_FE(dbase_close,                                                             NULL)
 
737
        PHP_FE(dbase_numrecords,                                                NULL)
 
738
        PHP_FE(dbase_numfields,                                                 NULL)
 
739
        PHP_FE(dbase_add_record,                                                NULL)
 
740
        PHP_FE(dbase_replace_record,                                    NULL)
 
741
        PHP_FE(dbase_get_record,                                                NULL)
 
742
        PHP_FE(dbase_get_record_with_names,                             NULL)
 
743
        PHP_FE(dbase_delete_record,                                             NULL)
 
744
        PHP_FE(dbase_pack,                                                              NULL)
 
745
        PHP_FE(dbase_get_header_info,                                   NULL)
 
746
        {NULL, NULL, NULL}
 
747
};
 
748
/* }}} */
 
749
 
 
750
/* Added by Zak Greant <zak@php.net> */
 
751
/* {{{ proto array dbase_get_header_info(int database_handle)
 
752
 */
 
753
PHP_FUNCTION(dbase_get_header_info)
 
754
{
 
755
        zval            **dbh_id, *row;
 
756
        dbfield_t       *dbf, *cur_f;
 
757
        dbhead_t        *dbh;
 
758
        int             dbh_type;
 
759
        DBase_TLS_VARS; 
 
760
 
 
761
        if (ZEND_NUM_ARGS() != 1 || (zend_get_parameters_ex(1, &dbh_id) == FAILURE)) {
 
762
                WRONG_PARAM_COUNT;
 
763
        }
 
764
        convert_to_long_ex(dbh_id);
 
765
 
 
766
        dbh = zend_list_find(Z_LVAL_PP(dbh_id), &dbh_type);
 
767
        if (!dbh || dbh_type != DBase_GLOBAL(le_dbhead)) {
 
768
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find database for identifier %ld", Z_LVAL_PP(dbh_id));
 
769
                RETURN_FALSE;
 
770
        }
 
771
 
 
772
        array_init(return_value);
 
773
 
 
774
        dbf = dbh->db_fields;
 
775
        for (cur_f = dbf; cur_f < &dbh->db_fields[dbh->db_nfields]; ++cur_f) {
 
776
                MAKE_STD_ZVAL(row);
 
777
                array_init(row);
 
778
                
 
779
                add_next_index_zval(return_value, row);
 
780
                
 
781
                /* field name */
 
782
                add_assoc_string(row, "name", cur_f->db_fname, 1);
 
783
                
 
784
                /* field type */
 
785
                switch (cur_f->db_type) {
 
786
                        case 'C': add_assoc_string(row, "type", "character", 1);        break;
 
787
                        case 'D': add_assoc_string(row, "type", "date", 1);             break;
 
788
                        case 'I': add_assoc_string(row, "type", "integer", 1);          break;
 
789
                        case 'N': add_assoc_string(row, "type", "number", 1);           break;
 
790
                        case 'L': add_assoc_string(row, "type", "boolean", 1);          break;
 
791
                        case 'M': add_assoc_string(row, "type", "memo", 1);                     break;
 
792
                        default:  add_assoc_string(row, "type", "unknown", 1);          break;
 
793
                }
 
794
                
 
795
                /* length of field */
 
796
                add_assoc_long(row, "length", cur_f->db_flen);
 
797
                
 
798
                /* number of decimals in field */
 
799
                switch (cur_f->db_type) {
 
800
                        case 'N':
 
801
                        case 'I':
 
802
                                add_assoc_long(row, "precision", cur_f->db_fdc);
 
803
                                break;
 
804
                        default:
 
805
                                add_assoc_long(row, "precision", 0);
 
806
                }
 
807
 
 
808
                /* format for printing %s etc */
 
809
                add_assoc_string(row, "format", cur_f->db_format, 1);
 
810
                
 
811
                /* offset within record */
 
812
                add_assoc_long(row, "offset", cur_f->db_foffset);
 
813
        }
 
814
}
 
815
/* }}} */
 
816
 
 
817
zend_module_entry dbase_module_entry = {
 
818
        STANDARD_MODULE_HEADER,
 
819
        "dbase", dbase_functions, PHP_MINIT(dbase), PHP_MSHUTDOWN(dbase), NULL, NULL, NULL, NO_VERSION_YET, STANDARD_MODULE_PROPERTIES
 
820
};
 
821
 
 
822
 
 
823
#ifdef COMPILE_DL_DBASE
 
824
ZEND_GET_MODULE(dbase)
 
825
 
 
826
#if defined(PHP_WIN32) && defined(THREAD_SAFE)
 
827
 
 
828
/*NOTE: You should have an odbc.def file where you
 
829
export DllMain*/
 
830
BOOL WINAPI DllMain(HANDLE hModule, 
 
831
                      DWORD  ul_reason_for_call, 
 
832
                      LPVOID lpReserved)
 
833
{
 
834
    return 1;
 
835
}
 
836
#endif
 
837
#endif
 
838
 
 
839
#endif
 
840
 
 
841
/*
 
842
 * Local variables:
 
843
 * tab-width: 4
 
844
 * c-basic-offset: 4
 
845
 * End:
 
846
 * vim600: sw=4 ts=4 fdm=marker
 
847
 * vim<600: sw=4 ts=4
 
848
 */