I expected you will not have a problem that I have not gotten back to you,
since
it took you 6 mos to get back to me, and now I have to dig through archives
to find the source code.
The code is attached.
filepro_is_deleted is the new function
At 12:23 PM 2/20/01 +0000, you wrote:
>ID: 5440
>Updated by: sniper
>Reported By: [EMAIL PROTECTED]
>Old-Status: Feedback
>Status: Closed
>Old-Bug Type: filePro related
>Bug Type: Feature/Change Request
>Assigned To:
>Comments:
>
>No feedback. Changed to change request. Reopen if still a problem for you.
>
>--Jani
>
>
>Previous Comments:
>---------------------------------------------------------------------------
>
>[2001-01-18 09:40:47] [EMAIL PROTECTED]
>If you have made some improvements for the code,
>please send a patch made against the latest CVS
>(cvs diff -u)
>and someone will commit it if it is good.
>
>--Jani
>
>---------------------------------------------------------------------------
>
>[2000-07-07 20:32:08] [EMAIL PROTECTED]
>filepro access has some major design flaws.
>
>The two functions that are currently used to pull data from a db are
>filepro_rowcount, and filepro_retrieve. filepro_rowcount returns the
>number of rows in the db that are NOT deleted. filepro_retrieve returns a
>row/column of the database, regardless of whether or not the row is (not)
>deleted. This makes it impossible for php to actually retrieve only the
>undeleted rows from the table.
>
>Recommendations:
>We have added an additional function in order to check if a row is deleted
>(filepro_is_deleted), and are happy to contribute this code. However,
>because of the inefficiency of the current retrieve function, we recommend
>adding a new function to obsolete the retrieve function. This function
>should be written like the dbase getrecord function, that returns a
>deleted member along with all the fields in a given record.
>
>In addition, the filepro_rowcount function is essentially useless, since
>it gives you the number of undeleted records. In order to improve the
>results of someone who is currently using this to iterate through their
>db, it is recommended that this function be changed to return the total
>(deleted or undeleted) number of records.
>
>---------------------------------------------------------------------------
>
>
>
>ATTENTION! Do NOT reply to this email!
>To reply, use the web interface found at http://bugs.php.net/?id=5440&edit=2
/*
+----------------------------------------------------------------------+
| PHP version 4.0 |
+----------------------------------------------------------------------+
| Copyright (c) 1997, 1998, 1999, 2000 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 2.02 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available at through the world-wide-web at |
| http://www.php.net/license/2_02.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Chad Robinson <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
filePro 4.x support developed by Chad Robinson, [EMAIL PROTECTED]
Contact Chad Robinson at BRT Technical Services Corp. for details.
filePro is a registered trademark by Fiserv, Inc. This file contains
no code or information that is not freely available from the filePro
web site at http://www.fileproplus.com/
*/
#include "php.h"
#include "safe_mode.h"
#include "fopen-wrappers.h"
#include <string.h>
#ifdef PHP_WIN32
#include <windows.h>
#else
#include <sys/param.h>
#endif
#include <errno.h>
#include "php_globals.h"
#include "php_filepro.h"
#if HAVE_FILEPRO
typedef struct fp_field {
char *name;
char *format;
int width;
struct fp_field *next;
} FP_FIELD;
#ifdef THREAD_SAFE
DWORD FPTls;
static int numthreads=0;
typedef struct fp_global_struct{
char *fp_database;
signed int fp_fcount;
signed int fp_keysize;
FP_FIELD *fp_fieldlist;
}fp_global_struct;
#define FP_GLOBAL(a) fp_globals->a
#define FP_TLS_VARS \
fp_global_struct *fp_globals; \
fp_globals=TlsGetValue(FPTls);
#else
#define FP_GLOBAL(a) a
#define FP_TLS_VARS
static char *fp_database = NULL; /* Database
directory */
static signed int fp_fcount = -1; /* Column count */
static signed int fp_keysize = -1; /* Size of key
records */
static FP_FIELD *fp_fieldlist = NULL; /* List of fields */
#endif
PHP_MINIT_FUNCTION(filepro)
{
#ifdef THREAD_SAFE
fp_global_struct *fp_globals;
#if defined(COMPILE_DL) || defined(COMPILE_DL_FILEPRO)
CREATE_MUTEX(fp_mutex,"FP_TLS");
SET_MUTEX(fp_mutex);
numthreads++;
if (numthreads==1){
if ((FPTls=TlsAlloc())==0xFFFFFFFF){
FREE_MUTEX(fp_mutex);
return 0;
}}
FREE_MUTEX(fp_mutex);
#endif
fp_globals = (fp_global_struct *) LocalAlloc(LPTR,
sizeof(fp_global_struct));
TlsSetValue(FPTls, (void *) fp_globals);
#endif
FP_GLOBAL(fp_database)=NULL;
FP_GLOBAL(fp_fcount)=-1;
FP_GLOBAL(fp_keysize)=-1;
FP_GLOBAL(fp_fieldlist)=NULL;
return SUCCESS;
}
PHP_MSHUTDOWN_FUNCTION(filepro)
{
#ifdef THREAD_SAFE
fp_global_struct *fp_globals;
fp_globals = TlsGetValue(FPTls);
if (fp_globals != 0)
LocalFree((HLOCAL) fp_globals);
#if defined(COMPILE_DL) || defined(COMPILE_DL_FILEPRO)
SET_MUTEX(fp_mutex);
numthreads--;
if (!numthreads){
if (!TlsFree(FPTls)){
FREE_MUTEX(fp_mutex);
return 0;
}}
FREE_MUTEX(fp_mutex);
#endif
#endif
return SUCCESS;
}
function_entry filepro_functions[] = {
PHP_FE(filepro,
NULL)
PHP_FE(filepro_rowcount,
NULL)
PHP_FE(filepro_fieldname,
NULL)
PHP_FE(filepro_fieldtype,
NULL)
PHP_FE(filepro_fieldwidth,
NULL)
PHP_FE(filepro_fieldcount,
NULL)
PHP_FE(filepro_retrieve,
NULL)
PHP_FE(filepro_is_deleted,
NULL)
{NULL, NULL, NULL}
};
zend_module_entry filepro_module_entry = {
"filepro", filepro_functions, PHP_MINIT(filepro),
PHP_MSHUTDOWN(filepro), NULL, NULL, NULL, STANDARD_MODULE_PROPERTIES
};
#if defined(COMPILE_DL) || defined(COMPILE_DL_FILEPRO)
#include "dl/phpdl.h"
ZEND_GET_MODULE(filepro)
#if (WIN32|WINNT) && defined(THREAD_SAFE)
/*NOTE: You should have an odbc.def file where you
export DllMain*/
BOOL WINAPI DllMain(HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
switch( ul_reason_for_call ) {
case DLL_PROCESS_ATTACH:
if ((FPTls=TlsAlloc())==0xFFFFFFFF){
return 0;
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
if (!TlsFree(FPTls)){
return 0;
}
break;
}
return 1;
}
#endif
#endif
/*
* LONG filePro(STRING directory)
*
* Read and verify the map file. We store the field count and field info
* internally, which means we become unstable if you modify the table while
* a user is using it! We cannot lock anything since Web connections don't
* provide the ability to later unlock what we locked. Be smart, be safe.
*/
PHP_FUNCTION(filepro)
{
pval *dir;
FILE *fp;
char workbuf[256]; /* FIX - should really be the max filename
length */
char readbuf[256];
char *strtok_buf = NULL;
int i;
FP_FIELD *new_field, *tmp;
PLS_FETCH();
FP_TLS_VARS;
if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &dir) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_string(dir);
/* FIX - we should really check and free these if they are used! */
FP_GLOBAL(fp_database) = NULL;
FP_GLOBAL(fp_fieldlist) = NULL;
FP_GLOBAL(fp_fcount) = -1;
FP_GLOBAL(fp_keysize) = -1;
sprintf(workbuf, "%s/map", dir->value.str.val);
if (PG(safe_mode) && (!php_checkuid(workbuf, 2))) {
RETURN_FALSE;
}
if (php_check_open_basedir(workbuf)) {
RETURN_FALSE;
}
if (!(fp = V_FOPEN(workbuf, "r"))) {
php_error(E_WARNING, "filePro: cannot open map: [%d] %s",
errno, strerror(errno));
RETURN_FALSE;
}
if (!fgets(readbuf, 250, fp)) {
fclose(fp);
php_error(E_WARNING, "filePro: cannot read map: [%d] %s",
errno, strerror(errno));
RETURN_FALSE;
}
/* Get the field count, assume the file is readable! */
if (strcmp(php_strtok_r(readbuf, ":", &strtok_buf), "map")) {
php_error(E_WARNING, "filePro: map file corrupt or
encrypted");
RETURN_FALSE;
}
FP_GLOBAL(fp_keysize) = atoi(php_strtok_r(NULL, ":", &strtok_buf));
php_strtok_r(NULL, ":", &strtok_buf);
FP_GLOBAL(fp_fcount) = atoi(php_strtok_r(NULL, ":", &strtok_buf));
/* Read in the fields themselves */
for (i = 0; i < FP_GLOBAL(fp_fcount); i++) {
if (!fgets(readbuf, 250, fp)) {
fclose(fp);
php_error(E_WARNING, "filePro: cannot read map:
[%d] %s",
errno, strerror(errno));
RETURN_FALSE;
}
new_field = emalloc(sizeof(FP_FIELD));
new_field->next = NULL;
new_field->name = estrdup(php_strtok_r(readbuf, ":",
&strtok_buf));
new_field->width = atoi(php_strtok_r(NULL, ":", &strtok_buf));
new_field->format = estrdup(php_strtok_r(NULL, ":",
&strtok_buf));
/* Store in forward-order to save time later */
if (!FP_GLOBAL(fp_fieldlist)) {
FP_GLOBAL(fp_fieldlist) = new_field;
} else {
for (tmp = FP_GLOBAL(fp_fieldlist); tmp; tmp =
tmp->next) {
if (!tmp->next) {
tmp->next = new_field;
tmp = new_field;
}
}
}
}
fclose(fp);
FP_GLOBAL(fp_database) =
estrndup(dir->value.str.val,dir->value.str.len);
RETVAL_TRUE;
}
/*
* LONG filePro_rowcount(void)
*
* Count the used rows in the database. filePro just marks deleted records
* as deleted; they are not removed. Since no counts are maintained we need
* to go in and count records ourselves. <sigh>
*
* Errors return false, success returns the row count.
*/
PHP_FUNCTION(filepro_rowcount)
{
FILE *fp;
char workbuf[MAXPATHLEN];
char readbuf[256];
int recsize = 0, records = 0;
PLS_FETCH();
FP_TLS_VARS;
if (ARG_COUNT(ht) != 0) {
WRONG_PARAM_COUNT;
}
if (!FP_GLOBAL(fp_database)) {
php_error(E_WARNING,
"filePro: must set database
directory first!\n");
RETURN_FALSE;
}
recsize = FP_GLOBAL(fp_keysize) + 19; /* 20 bytes system info -1
to save time later */
/* Now read the records in, moving forward recsize-1 bytes each
time */
sprintf(workbuf, "%s/key", FP_GLOBAL(fp_database));
if (PG(safe_mode) && (!php_checkuid(workbuf, 2))) {
RETURN_FALSE;
}
if (php_check_open_basedir(workbuf)) {
RETURN_FALSE;
}
if (!(fp = V_FOPEN(workbuf, "r"))) {
php_error(E_WARNING, "filePro: cannot open key: [%d] %s",
errno, strerror(errno));
RETURN_FALSE;
}
while (!feof(fp)) {
if (fread(readbuf, 1, 1, fp) == 1) {
if (readbuf[0])
records++;
fseek(fp, recsize, SEEK_CUR);
}
}
fclose(fp);
RETVAL_LONG(records);
}
/*
* STRING filePro_fieldname(LONG field_number)
*
* Errors return false, success returns the name of the field.
*/
PHP_FUNCTION(filepro_fieldname)
{
pval *fno;
FP_FIELD *lp;
int i;
FP_TLS_VARS;
if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &fno) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(fno);
if (!FP_GLOBAL(fp_database)) {
php_error(E_WARNING,
"filePro: must set database
directory first!\n");
RETURN_FALSE;
}
for (i = 0, lp = FP_GLOBAL(fp_fieldlist); lp; lp = lp->next, i++) {
if (i == fno->value.lval) {
RETURN_STRING(lp->name,1);
}
}
php_error(E_WARNING,
"filePro: unable to locate field number
%d.\n",
fno->value.lval);
RETVAL_FALSE;
}
/*
* STRING filePro_fieldtype(LONG field_number)
*
* Errors return false, success returns the type (edit) of the field
*/
PHP_FUNCTION(filepro_fieldtype)
{
pval *fno;
FP_FIELD *lp;
int i;
FP_TLS_VARS;
if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &fno) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(fno);
if (!FP_GLOBAL(fp_database)) {
php_error(E_WARNING,
"filePro: must set database
directory first!\n");
RETURN_FALSE;
}
for (i = 0, lp = FP_GLOBAL(fp_fieldlist); lp; lp = lp->next, i++) {
if (i == fno->value.lval) {
RETURN_STRING(lp->format,1);
}
}
php_error(E_WARNING,
"filePro: unable to locate field number
%d.\n",
fno->value.lval);
RETVAL_FALSE;
}
/*
* STRING filePro_fieldwidth(int field_number)
*
* Errors return false, success returns the character width of the field.
*/
PHP_FUNCTION(filepro_fieldwidth)
{
pval *fno;
FP_FIELD *lp;
int i;
FP_TLS_VARS;
if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &fno) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(fno);
if (!FP_GLOBAL(fp_database)) {
php_error(E_WARNING,
"filePro: must set database
directory first!\n");
RETURN_FALSE;
}
for (i = 0, lp = FP_GLOBAL(fp_fieldlist); lp; lp = lp->next, i++) {
if (i == fno->value.lval) {
RETURN_LONG(lp->width);
}
}
php_error(E_WARNING,
"filePro: unable to locate field number
%d.\n",
fno->value.lval);
RETVAL_FALSE;
}
/*
* LONG filePro_fieldcount(void)
*
* Errors return false, success returns the field count.
*/
PHP_FUNCTION(filepro_fieldcount)
{
FP_TLS_VARS;
if (ARG_COUNT(ht) != 0) {
WRONG_PARAM_COUNT;
}
if (!FP_GLOBAL(fp_database)) {
php_error(E_WARNING,
"filePro: must set database
directory first!\n");
RETURN_FALSE;
}
/* Read in the first line from the map file */
RETVAL_LONG(FP_GLOBAL(fp_fcount));
}
/*
* STRING filePro_retrieve(int row_number, int field_number)
*
* Errors return false, success returns the datum.
*/
PHP_FUNCTION(filepro_retrieve)
{
pval *rno, *fno;
FP_FIELD *lp;
FILE *fp;
char workbuf[MAXPATHLEN];
char readbuf[1024]; /* FIX - Work out better buffering! */
int i, fnum, rnum;
long offset;
PLS_FETCH();
FP_TLS_VARS;
if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &rno, &fno) ==
FAILURE) {
WRONG_PARAM_COUNT;
}
if (!FP_GLOBAL(fp_database)) {
php_error(E_WARNING,
"filePro: must set database
directory first!\n");
RETURN_FALSE;
}
convert_to_long(rno);
convert_to_long(fno);
fnum = fno->value.lval;
rnum = rno->value.lval;
if (rnum < 0 || fnum < 0 || fnum >= FP_GLOBAL(fp_fcount)) {
php_error(E_WARNING, "filepro: parameters out of range");
RETURN_FALSE;
}
offset = (rnum + 1) * (FP_GLOBAL(fp_keysize) + 20) + 20; /* Record
location */
for (i = 0, lp = FP_GLOBAL(fp_fieldlist); lp && i < fnum; lp =
lp->next, i++) {
offset += lp->width;
}
if (!lp) {
php_error(E_WARNING, "filePro: cannot locate field");
RETURN_FALSE;
}
/* Now read the record in */
sprintf(workbuf, "%s/key", FP_GLOBAL(fp_database));
if (PG(safe_mode) && (!php_checkuid(workbuf, 2))) {
RETURN_FALSE;
}
if (php_check_open_basedir(workbuf)) {
RETURN_FALSE;
}
if (!(fp = V_FOPEN(workbuf, "r"))) {
php_error(E_WARNING, "filePro: cannot open key: [%d] %s",
errno, strerror(errno));
fclose(fp);
RETURN_FALSE;
}
fseek(fp, offset, SEEK_SET);
if (fread(readbuf, lp->width, 1, fp) != 1) {
php_error(E_WARNING, "filePro: cannot read data: [%d] %s",
errno, strerror(errno));
fclose(fp);
RETURN_FALSE;
}
readbuf[lp->width] = '\0';
fclose(fp);
RETURN_STRING(readbuf,1);
}
/*
* LONG filePro_is_deleted(int row_number)
*
* return 1 if deleted (or invalid), 0 if not deleted
*/
PHP_FUNCTION(filepro_is_deleted)
{
pval *rno;
FP_FIELD *lp;
FILE *fp;
char workbuf[MAXPATHLEN];
char readbuf[1024]; /* FIX - Work out better buffering! */
int i, rnum;
long offset;
PLS_FETCH();
FP_TLS_VARS;
if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &rno) == FAILURE) {
WRONG_PARAM_COUNT;
}
if (!FP_GLOBAL(fp_database)) {
php_error(E_WARNING,
"filePro: must set database
directory first!\n");
RETURN_TRUE;
}
convert_to_long(rno);
rnum = rno->value.lval;
if (rnum < 0) {
php_error(E_WARNING, "filepro: parameters out of range");
RETURN_TRUE;
}
offset = (rnum + 1) * (FP_GLOBAL(fp_keysize) + 20) ; /* Record location */
/* Now read the record in */
sprintf(workbuf, "%s/key", FP_GLOBAL(fp_database));
if (PG(safe_mode) && (!php_checkuid(workbuf, 2))) {
RETURN_TRUE;
}
if (php_check_open_basedir(workbuf)) {
RETURN_TRUE;
}
if (!(fp = V_FOPEN(workbuf, "r"))) {
php_error(E_WARNING, "filePro: cannot open key: [%d] %s",
errno, strerror(errno));
fclose(fp);
RETURN_TRUE;
}
fseek(fp, offset, SEEK_SET);
if (fread(readbuf, 1, 1, fp) != 1) {
php_error(E_WARNING, "filePro: cannot read data: [%d] %s",
errno, strerror(errno));
fclose(fp);
RETURN_TRUE;
}
if( readbuf[0] ){
fclose(fp);
RETURN_FALSE;
}
fclose(fp);
RETURN_TRUE;
}
#endif
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
===========================================================
Michael Gile [EMAIL PROTECTED]
President (518)435-0682
Web Services Group http://www.wsg.net
--
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]