From: Stig Bakken Date: Tue, 15 Jun 1999 17:06:22 +0000 (+0000) Subject: * now using php4.ini instead of php3.ini X-Git-Tag: BEFORE_REMOVING_GC_STEP1~134 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=336392ea6ced0f77f988748b10dc37fe5fb094d8;p=php * now using php4.ini instead of php3.ini * re-imported fopen-wrappers, fsock and string code from php3 NB! I have not tested all of the imported functions yet. --- diff --git a/cgi_main.c b/cgi_main.c index 15fc418da5..c98d56e1db 100644 --- a/cgi_main.c +++ b/cgi_main.c @@ -145,7 +145,7 @@ static void php_cgi_usage(char *argv0) " -s Display colour syntax highlighted source.\n" " -f Parse . Implies `-q'\n" " -v Version number\n" - " -c Look for php3.ini file in this directory\n" + " -c Look for php4.ini file in this directory\n" #if SUPPORT_INTERACTIVE " -a Run interactively\n" #endif @@ -235,7 +235,7 @@ set. This variable is set, for example, by Apache's Action directive redirect.\ --disable-force-cgi-redirect switch. If you do this and you have your PHP CGI\n\ binary accessible somewhere in your web tree, people will be able to circumvent\n\ .htaccess security by loading files through the PHP parser. A good way around\n\ -this is to define doc_root in your php3.ini file to something other than your\n\ +this is to define doc_root in your php4.ini file to something other than your\n\ top-level DOCUMENT_ROOT. This way you can separate the part of your web space\n\n\ which uses PHP from the normal part using .htaccess security. If you do not have\n\ any .htaccess restrictions anywhere on your site you can leave doc_root undefined.\n\ diff --git a/ext/standard/file.c b/ext/standard/file.c index eef2696b92..56325f5879 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP HTML Embedded Scripting Language Version 3.0 | +----------------------------------------------------------------------+ - | Copyright (c) 1997,1998 PHP Development Team (See Credits file) | + | Copyright (c) 1997-1999 PHP Development Team (See Credits file) | +----------------------------------------------------------------------+ | This program is free software; you can redistribute it and/or modify | | it under the terms of one of the following licenses: | @@ -13,7 +13,7 @@ | | | B) the PHP License as published by the PHP Development Team and | | included in the distribution in the file: LICENSE | - | | + | | | This program is distributed in the hope that it will be useful, | | but WITHOUT ANY WARRANTY; without even the implied warranty of | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | @@ -29,7 +29,6 @@ /* $Id$ */ #include "php.h" #include "php_globals.h" -#include "ext/standard/flock_compat.h" #include #include @@ -48,10 +47,8 @@ #include /* #include */ #endif -#include "ext/standard/head.h" #include "safe_mode.h" -#include "php3_string.h" -#include "file.h" +#include "php3_standard.h" #if HAVE_PWD_H #if MSVC5 #include "win32/pwd.h" @@ -62,17 +59,25 @@ #if HAVE_SYS_TIME_H #include #endif +#if MSVC5 +#include +#else +#include +#include +#include +#endif #include "snprintf.h" #include "fsock.h" #include "fopen-wrappers.h" -#include "php_globals.h" + +#if HAVE_SYS_FILE_H +#include +#endif #if MISSING_FCLOSE_DECL extern int fclose(); #endif -static void _php3_closesocket(int *); - #ifndef THREAD_SAFE static int fgetss_state = 0; int le_fp,le_pp; @@ -125,8 +130,8 @@ extern int le_uploads; # endif #endif - -char *tempnam(const char *dir, const char *pfx) +char * +tempnam(const char *dir, const char *pfx) { int save_errno; char *f, *name; @@ -171,37 +176,37 @@ char *tempnam(const char *dir, const char *pfx) } #endif - function_entry php3_file_functions[] = { - {"pclose", php3_pclose, NULL}, - {"popen", php3_popen, NULL}, - {"readfile", php3_readfile, NULL}, - {"rewind", php3_rewind, NULL}, - {"rmdir", php3_rmdir, NULL}, + PHP_FE(pclose, NULL) + PHP_FE(popen, NULL) + PHP_FE(readfile, NULL) + PHP_FE(rewind, NULL) {"umask", php3_fileumask, NULL}, - {"fclose", php3_fclose, NULL}, - {"feof", php3_feof, NULL}, - {"fgetc", php3_fgetc, NULL}, - {"fgets", php3_fgets, NULL}, - {"fgetss", php3_fgetss, NULL}, - {"fread", php3_fread, NULL}, - {"fopen", php3_fopen, NULL}, - {"fpassthru", php3_fpassthru, NULL}, - {"fseek", php3_fseek, NULL}, - {"ftell", php3_ftell, NULL}, - {"fwrite", php3_fwrite, NULL}, + PHP_FE(rmdir, NULL) + PHP_FE(fclose, NULL) + PHP_FE(feof, NULL) + PHP_FE(fgetc, NULL) + PHP_FE(fgets, NULL) + PHP_FE(fgetss, NULL) + PHP_FE(fpassthru, NULL) + PHP_FE(fread, NULL) + PHP_FE(fopen, NULL) + PHP_FE(fseek, NULL) + PHP_FE(ftell, NULL) + PHP_FE(fwrite, NULL) + PHP_FE(set_file_buffer, NULL) {"fputs", php3_fwrite, NULL}, - {"mkdir", php3_mkdir, NULL}, - {"rename", php3_rename, NULL}, + PHP_FE(mkdir, NULL) + PHP_FE(rename, NULL) {"copy", php3_file_copy, NULL}, - {"tempnam", php3_tempnam, NULL}, - {"file", php3_file, NULL}, - {"fgetcsv", php3_fgetcsv, NULL}, - PHP_FE(flock, NULL) - {"get_meta_tags", php3_get_meta_tags, NULL}, - {"set_socket_blocking", php3_set_socket_blocking, NULL}, + PHP_FE(tempnam, NULL) + PHP_FE(file, NULL) + PHP_FE(flock, NULL) + PHP_FE(fgetcsv, NULL) + PHP_FE(get_meta_tags, NULL) + PHP_FE(set_socket_blocking, NULL) #if (0 && HAVE_SYS_TIME_H && HAVE_SETSOCKOPT && defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)) - {"set_socket_timeout", php3_set_socket_timeout, NULL}, + PHP_FE(set_socket_timeout, NULL) #endif {NULL, NULL, NULL} }; @@ -210,64 +215,9 @@ php3_module_entry php3_file_module_entry = { "PHP_file", php3_file_functions, php3_minit_file, NULL, NULL, NULL, NULL, STANDARD_MODULE_PROPERTIES }; - -static int flock_values[] = { LOCK_SH, LOCK_EX, LOCK_UN }; - -/* {{{ proto bool flock(int fp, int operation) - portable file locking */ -PHP_FUNCTION(flock) -{ - pval *arg1, *arg2; - FILE *fp; - int type; - int issock=0; - int *sock, fd=0; - int act = 0; - - if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { - WRONG_PARAM_COUNT; - } - - convert_to_long(arg1); - convert_to_long(arg2); - - fp = php3_list_find(arg1->value.lval, &type); - if (type == wsa_fp){ - issock = 1; - sock = php3_list_find(arg1->value.lval, &type); - fd = *sock; - } - - if ((!fp || (type!=le_fp && type!=le_pp)) && (!fd || type!=wsa_fp)) { - php3_error(E_WARNING,"Unable to find file identifier %d",arg1->value.lval); - RETURN_FALSE; - } - - if (!issock) { - fd = fileno(fp); - } - - act = arg2->value.lval & 3; - if(act < 1 || act > 3) { - php3_error(E_WARNING, "illegal value for second argument"); - RETURN_FALSE; - } - /* flock_values contains all possible actions - if (arg2 & 4) we won't block on the lock */ - act = flock_values[act - 1] | (arg2->value.lval & 4 ? LOCK_NB : 0); - if (flock(fd, act) == -1) { - RETURN_FALSE; - } - - RETURN_TRUE; -} -/* }}} */ - - /* {{{ proto array get_meta_tags(string filename [, int use_include_path]) Extracts all meta tag content attributes from a file and returns an array */ -PHP_FUNCTION(get_meta_tags) -{ +void php3_get_meta_tags(INTERNAL_FUNCTION_PARAMETERS) { pval *filename, *arg2; FILE *fp; char buf[8192]; @@ -279,20 +229,20 @@ PHP_FUNCTION(get_meta_tags) /* check args */ switch (ARG_COUNT(ht)) { - case 1: - if (getParameters(ht,1,&filename) == FAILURE) { - WRONG_PARAM_COUNT; - } - break; - case 2: - if (getParameters(ht,2,&filename,&arg2) == FAILURE) { - WRONG_PARAM_COUNT; - } - convert_to_long(arg2); - use_include_path = arg2->value.lval; - break; - default: + case 1: + if (getParameters(ht,1,&filename) == FAILURE) { WRONG_PARAM_COUNT; + } + break; + case 2: + if (getParameters(ht,2,&filename,&arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg2); + use_include_path = arg2->value.lval; + break; + default: + WRONG_PARAM_COUNT; } convert_to_string(filename); @@ -307,11 +257,7 @@ PHP_FUNCTION(get_meta_tags) if (array_init(return_value)==FAILURE) { if (issock) { -#if WIN32|WINNT - closesocket(socketd); -#else - close(socketd); -#endif + SOCK_FCLOSE(socketd); } else { fclose(fp); } @@ -319,7 +265,7 @@ PHP_FUNCTION(get_meta_tags) } /* Now loop through the file and do the magic quotes thing if needed */ memset(buf,0,8191); - while((issock?SOCK_FGETS(buf,8191,socketd):fgets(buf,8191,fp) != NULL) + while((issock?SOCK_FGETS(buf,8191,socketd):fgets(buf,8191,fp)) != NULL && !php3i_stristr(buf,"")) { if(php3i_stristr(buf,"value.lval; - break; - default: + case 1: + if (getParameters(ht,1,&filename) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 2: + if (getParameters(ht,2,&filename,&arg2) == FAILURE) { WRONG_PARAM_COUNT; + } + convert_to_long(arg2); + use_include_path = arg2->value.lval; + break; + default: + WRONG_PARAM_COUNT; } convert_to_string(filename); @@ -442,7 +383,7 @@ PHP_FUNCTION(file) /* Now loop through the file and do the magic quotes thing if needed */ memset(buf,0,8191); - while(issock?SOCK_FGETS(buf,8191,socketd):fgets(buf,8191,fp) != NULL) { + while((issock?SOCK_FGETS(buf,8191,socketd):fgets(buf,8191,fp)) != NULL) { if (PG(magic_quotes_runtime)) { int len; @@ -453,11 +394,7 @@ PHP_FUNCTION(file) } } if (issock) { -#if WIN32|WINNT - closesocket(socketd); -#else - close(socketd); -#endif + SOCK_FCLOSE(socketd); } else { fclose(fp); } @@ -467,52 +404,46 @@ PHP_FUNCTION(file) static void __pclose(FILE *pipe) { + PLS_FETCH(); pclose_ret = pclose(pipe); } - static void _php3_closesocket(int *sock) { - int socketd=*sock; - if (socketd){ -#if WIN32|WINNT - closesocket(socketd); -#else - close(socketd); -#endif -#if HAVE_SHUTDOWN - shutdown(socketd, 0); -#endif + if(sock) { + SOCK_FCLOSE(*sock); efree(sock); } } - -static void _php3_unlink_uploaded_file(char *file) -{ +static void _php3_unlink_uploaded_file(char *file) { if(file) { unlink(file); } } +static void php3i_destructor_fclose(FILE *fp) { + (void)fclose(fp); +} int php3_minit_file(INIT_FUNC_ARGS) { - le_fp = register_list_destructors(fclose,NULL); + PLS_FETCH(); + + le_fp = register_list_destructors(php3i_destructor_fclose,NULL); le_pp = register_list_destructors(__pclose,NULL); wsa_fp = register_list_destructors(_php3_closesocket,NULL); le_uploads = register_list_destructors(_php3_unlink_uploaded_file,NULL); return SUCCESS; } - /* {{{ proto string tempnam(string dir, string prefix) Create a unique filename in a directory */ -PHP_FUNCTION(tempnam) -{ +void php3_tempnam(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1, *arg2; char *d; char *t; char p[64]; + PLS_FETCH(); if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { WRONG_PARAM_COUNT; @@ -528,11 +459,9 @@ PHP_FUNCTION(tempnam) } /* }}} */ - /* {{{ proto int fopen(string filename, string mode [, int use_include_path]) Open a file or a URL and return a file pointer */ -PHP_FUNCTION(fopen) -{ +void php3_fopen(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1, *arg2, *arg3; FILE *fp; char *p; @@ -540,22 +469,23 @@ PHP_FUNCTION(fopen) int id; int use_include_path = 0; int issock=0, socketd=0; + PLS_FETCH(); switch(ARG_COUNT(ht)) { - case 2: - if (getParameters(ht,2,&arg1,&arg2) == FAILURE) { - WRONG_PARAM_COUNT; - } - break; - case 3: - if (getParameters(ht,3,&arg1,&arg2,&arg3) == FAILURE) { - WRONG_PARAM_COUNT; - } - convert_to_long(arg3); - use_include_path = arg3->value.lval; - break; - default: + case 2: + if (getParameters(ht,2,&arg1,&arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 3: + if (getParameters(ht,3,&arg1,&arg2,&arg3) == FAILURE) { WRONG_PARAM_COUNT; + } + convert_to_long(arg3); + use_include_path = arg3->value.lval; + break; + default: + WRONG_PARAM_COUNT; } convert_to_string(arg1); convert_to_string(arg2); @@ -588,14 +518,13 @@ PHP_FUNCTION(fopen) } /* }}} */ - /* {{{ proto int fclose(int fp) Close an open file pointer */ -PHP_FUNCTION(fclose) -{ +void php3_fclose(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1; int id, type; FILE *fp; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; @@ -612,11 +541,9 @@ PHP_FUNCTION(fclose) } /* }}} */ - /* {{{ proto int popen(string command, string mode) Execute a command and open either a read or a write pipe to it */ -PHP_FUNCTION(popen) -{ +void php3_popen(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1, *arg2; FILE *fp; int id; @@ -631,51 +558,47 @@ PHP_FUNCTION(popen) convert_to_string(arg2); p = estrndup(arg2->value.str.val,arg2->value.str.len); if (PG(safe_mode)){ - b = strchr(arg1->value.str.val,' '); - if (!b) { - b = strrchr(arg1->value.str.val,'/'); - } else { - char *c; - c = arg1->value.str.val; - while((*b!='/')&&(b!=c)) { - b--; - } - if (b==c) { - b=NULL; - } - } - if (b) { - snprintf(buf,sizeof(buf),"%s%s",PG(safe_mode_exec_dir),b); - } else { - snprintf(buf,sizeof(buf),"%s/%s",PG(safe_mode_exec_dir),arg1->value.str.val); - } - fp = popen(buf,p); - if (!fp) { - php3_error(E_WARNING,"popen(\"%s\",\"%s\") - %s",buf,p,strerror(errno)); - RETURN_FALSE; - } + b = strchr(arg1->value.str.val,' '); + if (!b) { + b = strrchr(arg1->value.str.val,'/'); } else { - fp = popen(arg1->value.str.val,p); - if (!fp) { - php3_error(E_WARNING,"popen(\"%s\",\"%s\") - %s",arg1->value.str.val,p,strerror(errno)); - efree(p); - RETURN_FALSE; - } + char *c; + c = arg1->value.str.val; + while((*b!='/')&&(b!=c)) b--; + if (b==c) b=NULL; + } + if (b) { + snprintf(buf,sizeof(buf),"%s%s",PG(safe_mode_exec_dir),b); + } else { + snprintf(buf,sizeof(buf),"%s/%s",PG(safe_mode_exec_dir),arg1->value.str.val); + } + fp = popen(buf,p); + if (!fp) { + php3_error(E_WARNING,"popen(\"%s\",\"%s\") - %s",buf,p,strerror(errno)); + RETURN_FALSE; + } + } else { + fp = popen(arg1->value.str.val,p); + if (!fp) { + php3_error(E_WARNING,"popen(\"%s\",\"%s\") - %s",arg1->value.str.val,p,strerror(errno)); + efree(p); + RETURN_FALSE; + } } +/* #endif */ id = php3_list_insert(fp,le_pp); efree(p); RETURN_LONG(id); } /* }}} */ - /* {{{ proto int pclose(int fp) Close a file pointer opened by popen() */ -PHP_FUNCTION(pclose) -{ +void php3_pclose(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1; int id,type; FILE *fp; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; @@ -693,16 +616,15 @@ PHP_FUNCTION(pclose) } /* }}} */ - /* {{{ proto int feof(int fp) Test for end-of-file on a file pointer */ -PHP_FUNCTION(feof) -{ +void php3_feof(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1; FILE *fp; int id, type; int issock=0; int socketd=0, *sock; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; @@ -720,7 +642,7 @@ PHP_FUNCTION(feof) /* we're at the eof if the file doesn't exist */ RETURN_TRUE; } - if ((issock?(_php3_sock_eof(socketd)):feof(fp))) { + if ((issock?SOCK_FEOF(socketd):feof(fp))) { RETURN_TRUE; } else { RETURN_FALSE; @@ -728,15 +650,15 @@ PHP_FUNCTION(feof) } /* }}} */ - /* {{{ proto int set_socket_blocking(int socket descriptor, int mode) Set blocking/non-blocking mode on a socket */ -PHP_FUNCTION(set_socket_blocking) +void php3_set_socket_blocking(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1, *arg2; int id, type, block; int flags; int socketd=0, *sock; + PLS_FETCH(); if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { WRONG_PARAM_COUNT; @@ -752,6 +674,7 @@ PHP_FUNCTION(set_socket_blocking) RETURN_FALSE; } socketd=*sock; + _php3_sock_set_blocking(socketd, block == 0 ? 0 : 1); #if WIN32|WINNT /* with ioctlsocket, a non-zero sets nonblocking, a zero sets blocking */ flags=block; @@ -793,7 +716,7 @@ PHP_FUNCTION(set_socket_blocking) #if (0 && HAVE_SYS_TIME_H && HAVE_SETSOCKOPT && defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)) /* this doesn't work, as it appears those properties are read-only :( */ -PHP_FUNCTION(set_socket_timeout) +void php3_set_socket_timeout(INTERNAL_FUNCTION_PARAMETERS) { pval *socket,*timeout; int type, *sock; @@ -818,10 +741,9 @@ PHP_FUNCTION(set_socket_timeout) } #endif - /* {{{ proto string fgets(int fp, int length) Get a line from file pointer */ -PHP_FUNCTION(fgets) +void php3_fgets(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1, *arg2; FILE *fp; @@ -852,7 +774,7 @@ PHP_FUNCTION(fgets) buf = emalloc(sizeof(char) * (len + 1)); /* needed because recv doesnt put a null at the end*/ memset(buf,0,len+1); - if (!(issock?SOCK_FGETS(buf,len,socketd):fgets(buf,len,fp) != NULL)) { + if ((issock?SOCK_FGETS(buf,len,socketd):fgets(buf,len,fp)) == NULL) { efree(buf); RETVAL_FALSE; } else { @@ -868,16 +790,16 @@ PHP_FUNCTION(fgets) } /* }}} */ - /* {{{ proto string fgetc(int fp) Get a character from file pointer */ -PHP_FUNCTION(fgetc) { +void php3_fgetc(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1; FILE *fp; int id, type; char *buf; int issock=0; int *sock, socketd=0; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; @@ -896,7 +818,7 @@ PHP_FUNCTION(fgetc) { RETURN_FALSE; } buf = emalloc(sizeof(char) * 2); - if (!(issock?(SOCK_FGETC(buf,socketd)):(*buf=fgetc(fp)))) { + if (!(issock?(*buf=SOCK_FGETC(socketd)):(*buf=fgetc(fp)))) { efree(buf); RETVAL_FALSE; } else { @@ -905,22 +827,21 @@ PHP_FUNCTION(fgetc) { return_value->value.str.len = 1; return_value->type = IS_STRING; } - return; } /* }}} */ - /* Strip any HTML tags while reading */ /* {{{ proto string fgetss(int fp, int length) Get a line from file pointer and strip HTML tags */ -PHP_FUNCTION(fgetss) +void php3_fgetss(INTERNAL_FUNCTION_PARAMETERS) { pval *fd, *bytes; FILE *fp; - int id, len, br, type; - char *buf, *p, *rbuf, *rp, c, lc; + int id, len, type; + char *buf; int issock=0; int *sock,socketd=0; + PLS_FETCH(); if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &fd, &bytes) == FAILURE) { WRONG_PARAM_COUNT; @@ -946,98 +867,23 @@ PHP_FUNCTION(fgetss) buf = emalloc(sizeof(char) * (len + 1)); /*needed because recv doesnt set null char at end*/ memset(buf,0,len+1); - if (!(issock?SOCK_FGETS(buf,len,socketd):fgets(buf, len, fp) != NULL)) { + if (!((issock?SOCK_FGETS(buf,len,socketd):fgets(buf, len, fp)) != NULL)) { efree(buf); RETURN_FALSE; } - rbuf = estrdup(buf); - c = *buf; - lc = '\0'; - p = buf; - rp = rbuf; - br = 0; - - while (c) { - switch (c) { - case '<': - if (fgetss_state == 0) { - lc = '<'; - fgetss_state = 1; - } - break; - - case '(': - if (fgetss_state == 2) { - if (lc != '\"') { - lc = '('; - br++; - } - } else if (fgetss_state == 0) { - *(rp++) = c; - } - break; - - case ')': - if (fgetss_state == 2) { - if (lc != '\"') { - lc = ')'; - br--; - } - } else if (fgetss_state == 0) { - *(rp++) = c; - } - break; - - case '>': - if (fgetss_state == 1) { - lc = '>'; - fgetss_state = 0; - } else if (fgetss_state == 2) { - if (!br && lc != '\"') { - fgetss_state = 0; - } - } - break; - - case '\"': - if (fgetss_state == 2) { - if (lc == '\"') { - lc = '\0'; - } else if (lc != '\\') { - lc = '\"'; - } - } else if (fgetss_state == 0) { - *(rp++) = c; - } - break; - - case '?': - if (fgetss_state==1) { - br=0; - fgetss_state=2; - break; - } - /* fall-through */ - - default: - if (fgetss_state == 0) { - *(rp++) = c; - } - } - c = *(++p); - } - *rp = '\0'; - efree(buf); - RETVAL_STRING(rbuf,1); - efree(rbuf); + _php3_strip_tags(buf,fgetss_state); + RETURN_STRING(buf,0); } /* }}} */ +/* {{{ proto int fputs(int fp, string str [, int length]) + An alias for fwrite */ +/* }}} */ /* {{{ proto int fwrite(int fp, string str [, int length]) Binary-safe file write */ -PHP_FUNCTION(fwrite) +void php3_fwrite(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1, *arg2, *arg3=NULL; FILE *fp; @@ -1046,7 +892,7 @@ PHP_FUNCTION(fwrite) int issock=0; int *sock, socketd=0; PLS_FETCH(); - + switch (ARG_COUNT(ht)) { case 2: if (getParameters(ht, 2, &arg1, &arg2)==FAILURE) { @@ -1096,14 +942,66 @@ PHP_FUNCTION(fwrite) } /* }}} */ +/* {{{ proto int set_file_buffer(int fp, int buffer) +Set file write buffer */ +/* + wrapper for setvbuf() +*/ +void php3_set_file_buffer(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *arg1, *arg2; + FILE *fp; + int ret,id,type,buff; + int issock=0; + int *sock, socketd=0; + PLS_FETCH(); + + switch (ARG_COUNT(ht)) { + case 2: + if (getParameters(ht, 2, &arg1, &arg2)==FAILURE) { + RETURN_FALSE; + } + convert_to_long(arg1); + convert_to_long(arg2); + break; + default: + WRONG_PARAM_COUNT; + /* NOTREACHED */ + break; + } + + id = arg1->value.lval; + buff = arg2->value.lval; + fp = php3_list_find(id,&type); + if (type==wsa_fp){ + issock=1; + sock = php3_list_find(id,&type); + socketd=*sock; + } + if ((!fp || (type!=le_fp && type!=le_pp)) && (!socketd || type!=wsa_fp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + /* if buff is 0 then set to non-buffered */ + if(buff==0){ + ret=setvbuf(fp, NULL, _IONBF, 0); + } + else{ + ret=setvbuf(fp, NULL, _IOFBF, buff); + } + + RETURN_LONG(ret); +} +/* }}} */ /* {{{ proto int rewind(int fp) Rewind the position of a file pointer */ -PHP_FUNCTION(rewind) -{ +void php3_rewind(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1; int id,type; FILE *fp; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; @@ -1120,15 +1018,14 @@ PHP_FUNCTION(rewind) } /* }}} */ - /* {{{ proto int ftell(int fp) Get file pointer's read/write position */ -PHP_FUNCTION(ftell) -{ +void php3_ftell(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1; int id, type; long pos; FILE *fp; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; @@ -1145,15 +1042,14 @@ PHP_FUNCTION(ftell) } /* }}} */ - /* {{{ proto int fseek(int fp, int offset) Seek on a file pointer */ -PHP_FUNCTION(fseek) -{ +void php3_fseek(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1, *arg2; int ret,id,type; long pos; FILE *fp; + PLS_FETCH(); if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { WRONG_PARAM_COUNT; @@ -1182,11 +1078,9 @@ PHP_FUNCTION(fseek) } /* }}} */ - /* {{{ proto int mkdir(string pathname, int mode) Create a directory */ -PHP_FUNCTION(mkdir) -{ +void php3_mkdir(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1, *arg2; int ret,mode; PLS_FETCH(); @@ -1209,11 +1103,9 @@ PHP_FUNCTION(mkdir) } /* }}} */ - /* {{{ proto int rmdir(string dirname) Remove a directory */ -PHP_FUNCTION(rmdir) -{ +void php3_rmdir(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1; int ret; PLS_FETCH(); @@ -1234,17 +1126,17 @@ PHP_FUNCTION(rmdir) } /* }}} */ - /* {{{ proto int readfile(string filename [, int use_include_path]) Output a file or a URL */ -PHP_FUNCTION(readfile) -{ +void php3_readfile(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1, *arg2; char buf[8192]; FILE *fp; int b, size; int use_include_path = 0; + int issock=0, socketd=0; + PLS_FETCH(); /* check args */ switch (ARG_COUNT(ht)) { @@ -1278,16 +1170,14 @@ PHP_FUNCTION(readfile) RETURN_FALSE; } size= 0; - while(issock?(b=SOCK_FGETS(buf,sizeof(buf),socketd)):(b = fread(buf, 1, sizeof(buf), fp)) > 0) { - PHPWRITE(buf,b); - size += b ; + if (php3_header()) { /* force header if not already sent */ + while(issock?(b=SOCK_FREAD(buf,sizeof(buf),socketd)):(b = fread(buf, 1, sizeof(buf), fp)) > 0) { + PHPWRITE(buf,b); + size += b ; + } } if (issock) { -#if WIN32|WINNT - closesocket(socketd); -#else - close(socketd); -#endif + SOCK_FCLOSE(socketd); } else { fclose(fp); } @@ -1295,14 +1185,13 @@ PHP_FUNCTION(readfile) } /* }}} */ - /* {{{ proto int umask([int mask]) Return or change the umask */ -PHP_FUNCTION(fileumask) -{ +void php3_fileumask(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1; int oldumask; int arg_count = ARG_COUNT(ht); + PLS_FETCH(); oldumask = umask(077); @@ -1320,20 +1209,19 @@ PHP_FUNCTION(fileumask) } /* }}} */ - /* * Read to EOF on a file descriptor and write the output to stdout. */ /* {{{ proto int fpassthru(int fp) Output all remaining data from a file pointer */ -PHP_FUNCTION(fpassthru) -{ +void php3_fpassthru(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1; FILE *fp; char buf[8192]; int id, size, b, type; int issock=0; int socketd=0, *sock; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; @@ -1352,51 +1240,38 @@ PHP_FUNCTION(fpassthru) } size = 0; if (php3_header()) { /* force headers if not already sent */ - while(issock?(b=SOCK_FGETS(buf,sizeof(buf),socketd)):(b = fread(buf, 1, sizeof(buf), fp)) > 0) { + while(issock?(b=SOCK_FREAD(buf,sizeof(buf),socketd)):(b = fread(buf, 1, sizeof(buf), fp)) > 0) { PHPWRITE(buf,b); size += b ; } } -/* - if (issock) { -#if WIN32|WINNT - closesocket(socketd); -#else - close(socketd); -#endif - } else { - fclose(fp); - } -*/ php3_list_delete(id); RETURN_LONG(size); } /* }}} */ - /* {{{ proto int rename(string old_name, string new_name) Rename a file */ -PHP_FUNCTION(rename) -{ - pval *old_arg, *new_arg; - char *old_name, *new_name; +void php3_rename(INTERNAL_FUNCTION_PARAMETERS) { + pval *OLD, *NEW; + char *old, *new; int ret; PLS_FETCH(); - if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &old_arg, &new_arg) == FAILURE) { + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &OLD, &NEW) == FAILURE) { WRONG_PARAM_COUNT; } - convert_to_string(old_arg); - convert_to_string(new_arg); + convert_to_string(OLD); + convert_to_string(NEW); - old_name = old_arg->value.str.val; - new_name = new_arg->value.str.val; + old = OLD->value.str.val; + new = NEW->value.str.val; - if (PG(safe_mode) &&(!_php3_checkuid(old_name, 2))) { + if (PG(safe_mode) &&(!_php3_checkuid(old,2))) { RETURN_FALSE; } - ret = rename(old_name, new_name); + ret = rename(old, new); if (ret == -1) { php3_error(E_WARNING, @@ -1408,10 +1283,9 @@ PHP_FUNCTION(rename) } /* }}} */ - /* {{{ proto int copy(string source_file, string destination_file) Copy a file */ -PHP_FUNCTION(file_copy) +void php3_file_copy(INTERNAL_FUNCTION_PARAMETERS) { pval *source, *target; char buffer[8192]; @@ -1463,10 +1337,9 @@ PHP_FUNCTION(file_copy) } /* }}} */ - /* {{{ proto int fread(int fp, int length) Binary-safe file read */ -PHP_FUNCTION(fread) +void php3_fread(INTERNAL_FUNCTION_PARAMETERS) { pval *arg1, *arg2; FILE *fp; @@ -1500,7 +1373,7 @@ PHP_FUNCTION(fread) return_value->value.str.len = fread(return_value->value.str.val, 1, len, fp); return_value->value.str.val[return_value->value.str.len] = 0; } else { - return_value->value.str.len = _php3_sock_fread(return_value->value.str.val, len, socketd); + return_value->value.str.len = SOCK_FREAD(return_value->value.str.val, len, socketd); } if (PG(magic_quotes_runtime)) { return_value->value.str.val = _php3_addslashes(return_value->value.str.val,return_value->value.str.len,&return_value->value.str.len,1); @@ -1509,30 +1382,105 @@ PHP_FUNCTION(fread) } /* }}} */ - /* aparently needed for pdf to be compiled as a module under windows */ -PHPAPI int php3i_get_le_fp(void) -{ +PHPAPI int php3i_get_le_fp(void){ + PLS_FETCH(); return le_fp; } +static int flock_values[] = { LOCK_SH, LOCK_EX, LOCK_UN }; + +/* {{{ proto bool flock(int fp, int operation) + portable file locking */ +PHP_FUNCTION(flock) +{ + pval *arg1, *arg2; + FILE *fp; + int type; + int issock=0; + int *sock, fd=0; + int act = 0; + PLS_FETCH(); + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_long(arg1); + convert_to_long(arg2); + + fp = php3_list_find(arg1->value.lval, &type); + if (type == wsa_fp){ + issock = 1; + sock = php3_list_find(arg1->value.lval, &type); + fd = *sock; + } + + if ((!fp || (type!=le_fp && type!=le_pp)) && (!fd || type!=wsa_fp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",arg1->value.lval); + RETURN_FALSE; + } + + if (!issock) { + fd = fileno(fp); + } + + act = arg2->value.lval & 3; + if(act < 1 || act > 3) { + php3_error(E_WARNING, "illegal value for second argument"); + RETURN_FALSE; + } + /* flock_values contains all possible actions + if (arg2 & 4) we won't block on the lock */ + act = flock_values[act - 1] | (arg2->value.lval & 4 ? LOCK_NB : 0); + if (flock(fd, act) == -1) { + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + + /* {{{ proto array fgetcsv(int fp, int length) get line from file pointer and parse for CSV fields */ -PHP_FUNCTION(fgetcsv) { +void php3_fgetcsv(INTERNAL_FUNCTION_PARAMETERS) { char *temp, *tptr, *bptr; - char delimiter = ','; /* allow this to be set as parameter if required in future version? */ + char delimiter = ','; /* allow this to be set as parameter */ /* first section exactly as php3_fgetss */ - pval *fd, *bytes; + pval *fd, *bytes, *p_delim; FILE *fp; int id, len, type; char *buf; int issock=0; int *sock,socketd=0; + PLS_FETCH(); - if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &fd, &bytes) == FAILURE) { - WRONG_PARAM_COUNT; + switch(ARG_COUNT(ht)) { + case 2: + if (getParameters(ht, 2, &fd, &bytes) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + + case 3: + if (getParameters(ht, 3, &fd, &bytes, &p_delim) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string(p_delim); + /* Make sure that there is at least one character in string */ + if (p_delim->value.str.len < 1) { + WRONG_PARAM_COUNT; + } + /* use first character from string */ + delimiter = p_delim->value.str.val[0]; + break; + + default: + WRONG_PARAM_COUNT; + break; } convert_to_long(fd); @@ -1555,7 +1503,7 @@ PHP_FUNCTION(fgetcsv) { buf = emalloc(sizeof(char) * (len + 1)); /*needed because recv doesnt set null char at end*/ memset(buf,0,len+1); - if (!(issock?SOCK_FGETS(buf,len,socketd):fgets(buf, len, fp) != NULL)) { + if ((issock?SOCK_FGETS(buf,len,socketd):fgets(buf, len, fp)) == NULL) { efree(buf); RETURN_FALSE; } @@ -1589,7 +1537,7 @@ PHP_FUNCTION(fgetcsv) { do { /* 1. Strip any leading space */ - while isspace(*bptr) bptr++; + while(isspace(*bptr)) bptr++; /* 2. Read field, leaving bptr pointing at start of next field */ if (*bptr == '"') { /* 2A. handle quote delimited field */ diff --git a/ext/standard/file.h b/ext/standard/file.h index 2cad2035f7..fb873adf3b 100644 --- a/ext/standard/file.h +++ b/ext/standard/file.h @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP HTML Embedded Scripting Language Version 3.0 | +----------------------------------------------------------------------+ - | Copyright (c) 1997,1998 PHP Development Team (See Credits file) | + | Copyright (c) 1997-1999 PHP Development Team (See Credits file) | +----------------------------------------------------------------------+ | This program is free software; you can redistribute it and/or modify | | it under the terms of one of the following licenses: | @@ -32,37 +32,38 @@ #ifndef _FILE_H #define _FILE_H -extern php3_module_entry php3_file_module_entry; -#define php3_file_module_ptr &php3_file_module_entry +#ifndef INIT_FUNC_ARGS +#include "modules.h" +#endif extern int php3_minit_file(INIT_FUNC_ARGS); -PHP_FUNCTION(tempnam); -PHP_FUNCTION(fopen); -PHP_FUNCTION(fclose); -PHP_FUNCTION(popen); -PHP_FUNCTION(pclose); -PHP_FUNCTION(feof); -PHP_FUNCTION(fread); -PHP_FUNCTION(fgetc); -PHP_FUNCTION(fgets); -PHP_FUNCTION(fgetss); -PHP_FUNCTION(fgetcsv); -PHP_FUNCTION(fwrite); -PHP_FUNCTION(rewind); -PHP_FUNCTION(ftell); -PHP_FUNCTION(fseek); -PHP_FUNCTION(mkdir); -PHP_FUNCTION(rmdir); -PHP_FUNCTION(fpassthru); -PHP_FUNCTION(readfile); -PHP_FUNCTION(fileumask); -PHP_FUNCTION(rename); -PHP_FUNCTION(file_copy); -PHP_FUNCTION(file); -PHP_FUNCTION(set_socket_blocking); -PHP_FUNCTION(set_socket_timeout); -PHP_FUNCTION(get_meta_tags); -PHP_FUNCTION(flock); +extern void php3_tempnam(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_fopen(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_fclose(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_popen(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_pclose(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_feof(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_fread(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_fgetc(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_fgets(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_fgetss(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_fgetcsv(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_fwrite(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_set_file_buffer(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_rewind(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_ftell(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_fseek(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_mkdir(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_rmdir(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_fpassthru(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_readfile(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_fileumask(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_rename(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_file_copy(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_file(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_set_socket_blocking(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_set_socket_timeout(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_get_meta_tags(INTERNAL_FUNCTION_PARAMETERS); +extern PHP_FUNCTION(flock); -#define phpext_file_ptr php3_file_module_ptr #endif /* _FILE_H */ diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c index 29bb65ff66..c1115f9a9a 100644 --- a/ext/standard/fsock.c +++ b/ext/standard/fsock.c @@ -28,13 +28,22 @@ +----------------------------------------------------------------------+ */ /* $Id$ */ - #include "php.h" +#include "php_globals.h" #include +#include #if HAVE_UNISTD_H #include #endif +#if HAVE_FCNTL_H +#include +#endif + +#if HAVE_SYS_TIME_H +#include +#endif + #include #if HAVE_SYS_SOCKET_H #include @@ -84,11 +93,15 @@ function_entry fsock_functions[] = { struct php3i_sockbuf { int socket; - char *readbuf; + unsigned char *readbuf; size_t readbuflen; size_t readpos; size_t writepos; struct php3i_sockbuf *next; + struct php3i_sockbuf *prev; + char eof; + char persistent; + char is_blocked; }; static struct php3i_sockbuf *phpsockbuf; @@ -141,27 +154,102 @@ int _php3_is_persistent_sock(int sock) return 0; } /* }}} */ -/* {{{ _php3_fsockopen() */ + +/* {{{ connect_nonb */ +PHPAPI int connect_nonb(int sockfd, struct sockaddr *addr, int addrlen, struct timeval *timeout) + +/* probably won't work on Win32, someone else might try it (read: fix it ;) */ +#if !defined(WIN32) && (defined(O_NONBLOCK) || defined(O_NDELAY)) + +#ifndef O_NONBLOCK +#define O_NONBLOCK O_NDELAY +#endif + +{ + int flags; + int n; + int error = 0; + int len; + int ret = 0; + fd_set rset; + fd_set wset; + + flags = fcntl(sockfd, F_GETFL, 0); + fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); + + if((n = connect(sockfd, addr, addrlen)) < 0) + if(errno != EINPROGRESS) + return -1; + + if(n == 0) + goto ok; + + FD_ZERO(&rset); + FD_SET(sockfd, &rset); + + wset = rset; + + if((n = select(sockfd + 1, &rset, &wset, NULL, timeout)) == 0) { + error = ETIMEDOUT; + } + + if(FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) { + len = sizeof(error); + /* + BSD-derived systems set errno correctly + Solaris returns -1 from getsockopt in case of error + */ + if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) + ret = -1; + } else { + /* whoops: sockfd has disappeared */ + ret = -1; + } + +ok: + fcntl(sockfd, F_SETFL, flags); + + if(error) { + errno = error; + ret = -1; + } + return ret; +} +#else +//#warning "compiling without nonblocking connect support" +{ + return connect(sockfd, addr, addrlen); +} +#endif +/* }}} */ + + +/* {{{ _php3_fsockopen() */ /* This function takes an optional third argument which should be passed by reference. The error code from the connect call is written to this variable. */ static void _php3_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) { - pval *args[4]; + pval *args[5]; int *sock=emalloc(sizeof(int)); int *sockp; int id, arg_count=ARG_COUNT(ht); int socketd = -1; + struct timeval timeout = { 60, 0 }; unsigned short portno; char *key = NULL; + PLS_FETCH(); - if (arg_count > 4 || arg_count < 2 || getParametersArray(ht,arg_count,args)==FAILURE) { + if (arg_count > 5 || arg_count < 2 || getParametersArray(ht,arg_count,args)==FAILURE) { FREE_SOCK; WRONG_PARAM_COUNT; } switch(arg_count) { + case 5: + convert_to_long(args[4]); + timeout.tv_sec = args[4]->value.lval; case 4: if(!ParameterPassedByReference(ht,4)) { php3_error(E_WARNING,"error string argument to fsockopen not passed by reference"); @@ -188,7 +276,7 @@ static void _php3_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) { if (persistent && _php3_hash_find(&ht_keys, key, strlen(key) + 1, (void *) &sockp) == SUCCESS) { - efree(key); + FREE_SOCK; *sock = *sockp; RETURN_LONG(php3_list_insert(sock, wsa_fp)); } @@ -212,7 +300,7 @@ static void _php3_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) { server.sin_port = htons(portno); - if (connect(socketd, (struct sockaddr *)&server, sizeof(server)) == SOCK_CONN_ERR) { + if (connect_nonb(socketd, (struct sockaddr *)&server, sizeof(server), &timeout) == SOCK_CONN_ERR) { FREE_SOCK; if(arg_count>2) args[2]->value.lval = errno; if(arg_count>3) { @@ -235,7 +323,7 @@ static void _php3_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) { unix_addr.sun_family = AF_UNIX; strcpy(unix_addr.sun_path, args[0]->value.str.val); - if (connect(socketd, (struct sockaddr *) &unix_addr, sizeof(unix_addr)) == SOCK_CONN_ERR) { + if (connect_nonb(socketd, (struct sockaddr *) &unix_addr, sizeof(unix_addr), &timeout) == SOCK_CONN_ERR) { FREE_SOCK; if(arg_count>2) args[2]->value.lval = errno; if(arg_count>3) { @@ -267,19 +355,19 @@ static void _php3_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) { key, strlen(key) + 1, NULL); } if(key) efree(key); - id = php3_list_insert(sock,wsa_fp); + id = php3_list_insert(sock, wsa_fp); RETURN_LONG(id); } /* }}} */ -/* {{{ proto int fsockopen(string hostname, int port [, int errno [, string errstr]]) +/* {{{ proto int fsockopen(string hostname, int port [, int errno [, string errstr [, int timeout]]]) Open Internet or Unix domain socket connection */ PHP_FUNCTION(fsockopen) { _php3_fsockopen(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* }}} */ -/* {{{ proto int pfsockopen(string hostname, int port [, int errno [, string errstr]]) +/* {{{ proto int pfsockopen(string hostname, int port [, int errno [, string errstr [, int timeout]]]) Open persistent Internet or Unix domain socket connection */ PHP_FUNCTION(pfsockopen) { @@ -287,16 +375,37 @@ PHP_FUNCTION(pfsockopen) } /* }}} */ -/* Known issues with the socket buffering code: - * - does not work reliably with persistent sockets yet - * (buffered data is not persistent) - * - php3_fopen_url_wrapper() is still doing single-byte lookahead/read - */ +#define SOCK_DESTROY(sock) \ + if(sock->readbuf) pefree(sock->readbuf, sock->persistent); \ + if(sock->prev) sock->prev->next = sock->next; \ + if(sock->next) sock->next->prev = sock->prev; \ + if(sock == phpsockbuf) \ + phpsockbuf = sock->next; \ + pefree(sock, sock->persistent) -static php3i_sockbuf *_php3_sock_findsock(int socket) +static void php_cleanup_sockbuf(int persistent) { - /* FIXME: O(n) could be improved */ + php3i_sockbuf *now, *next; + + for(now = phpsockbuf; now; now = next) { + next = now->next; + if(now->persistent == persistent) { + SOCK_DESTROY(now); + } + } +} + +#define TOREAD(sock) ((sock)->writepos - (sock)->readpos) +#define READPTR(sock) ((sock)->readbuf + (sock)->readpos) +#define WRITEPTR(sock) ((sock)->readbuf + (sock)->writepos) +#define SOCK_FIND(sock,socket) \ + php3i_sockbuf *sock; \ + sock = _php3_sock_find(socket); \ + if(!sock) sock = _php3_sock_create(socket) + +static php3i_sockbuf *_php3_sock_find(int socket) +{ php3i_sockbuf *buf = NULL, *tmp; for(tmp = phpsockbuf; tmp; tmp = tmp->next) @@ -306,146 +415,223 @@ static php3i_sockbuf *_php3_sock_findsock(int socket) } return buf; +} + +static php3i_sockbuf *_php3_sock_create(int socket) +{ + php3i_sockbuf *sock; + int persistent = _php3_is_persistent_sock(socket); + + sock = pecalloc(sizeof(*sock), 1, persistent); + sock->socket = socket; + if((sock->next = phpsockbuf)) + phpsockbuf->prev = sock; + sock->persistent = persistent; + sock->is_blocked = 1; + phpsockbuf = sock; + + return sock; } -int _php3_sock_eof(int socket) +int _php3_sock_destroy(int socket) { - php3i_sockbuf *sockbuf; int ret = 0; + php3i_sockbuf *sock; - sockbuf = _php3_sock_findsock(socket); - if(sockbuf) { - ret = (sockbuf->writepos - sockbuf->readpos) == 0 ? 1 : 0; + sock = _php3_sock_find(socket); + if(sock) { + ret = 1; + SOCK_DESTROY(sock); } + return ret; } -/* {{{ _php3_sock_fgets() */ -int _php3_sock_fgets(char *buf, int maxlen, int socket) +int _php3_sock_close(int socket) { - struct php3i_sockbuf *sockbuf; - int bytesread, toread, len, buflen, count = 0; - char *nl; + int ret = 0; + php3i_sockbuf *sock; + + sock = _php3_sock_find(socket); + if(sock) { + if(!sock->persistent) { +#if HAVE_SHUTDOWN + shutdown(sock->socket, 0); +#endif +#if WIN32||WINNT + closesocket(sock->socket); +#else + close(sock->socket); +#endif + SOCK_DESTROY(sock); + } + } - sockbuf = _php3_sock_findsock(socket); + return ret; +} + +#define CHUNK_SIZE 2048 +#define MAX_CHUNKS_PER_READ 10 + + +static size_t _php3_sock_read_limited(php3i_sockbuf *sock, size_t max) +{ + char buf[CHUNK_SIZE]; + int nr_bytes; + size_t nr_read = 0; - if (sockbuf) { - toread = sockbuf->writepos - sockbuf->readpos; - if (toread > maxlen) { - toread = maxlen; - } - if ((nl = memchr(sockbuf->readbuf + sockbuf->readpos, '\n', toread)) != NULL) { - toread = (nl - (sockbuf->readbuf + sockbuf->readpos)) + 1; - } - memcpy(buf, sockbuf->readbuf + sockbuf->readpos, toread); - sockbuf->readpos += toread; - count += toread; - buf += toread; - if (sockbuf->readpos >= sockbuf->writepos) { - sockbuf->readpos = sockbuf->writepos = 0; - } - if (nl != NULL) { - /* if a newline was found, skip the recv() loop */ - goto sock_fgets_exit; + if(sock->eof || max > CHUNK_SIZE) return nr_read; + + nr_bytes = recv(sock->socket, buf, max, 0); + if(nr_bytes > 0) { + if(sock->writepos + nr_bytes > sock->readbuflen) { + sock->readbuflen += CHUNK_SIZE; + sock->readbuf = perealloc(sock->readbuf, sock->readbuflen, + sock->persistent); } + memcpy(WRITEPTR(sock), buf, nr_bytes); + sock->writepos += nr_bytes; + nr_read = nr_bytes; + } else if(nr_bytes == 0 || (nr_bytes < 0 && errno != EWOULDBLOCK)) { + sock->eof = 1; } - nl = NULL; - buflen = 0; - while (count < maxlen && nl == NULL) { - toread = maxlen - count; - bytesread = recv(socket, buf, toread, 0); - if (bytesread <= 0) { - break; - } - if ((nl = memchr(buf, '\n', bytesread)) != NULL) { - len = (nl - buf) + 1; - count += len; - buf += len; - if (len < bytesread) { - buflen = bytesread - len; - break; - } - } else { - count += bytesread; - buf += bytesread; - } + return nr_read; +} + +static size_t _php3_sock_read(php3i_sockbuf *sock) +{ + size_t nr_bytes; + size_t nr_read = 0; + int i; + + for(i = 0; !sock->eof && i < MAX_CHUNKS_PER_READ; i++) { + nr_bytes = _php3_sock_read_limited(sock, CHUNK_SIZE); + if(nr_bytes == 0) break; + nr_read += nr_bytes; } - if (buflen > 0) { /* there was data after the "\n" ... */ - if (sockbuf == NULL) { - sockbuf = emalloc(sizeof(struct php3i_sockbuf)); - sockbuf->socket = socket; - sockbuf->readbuf = emalloc(maxlen); - sockbuf->readbuflen = maxlen; - sockbuf->readpos = sockbuf->writepos = 0; - sockbuf->next = phpsockbuf; - phpsockbuf = sockbuf; - } else { - uint needlen = sockbuf->writepos + buflen; - - if (needlen > sockbuf->readbuflen) { - sockbuf->readbuflen += maxlen; - sockbuf->readbuf = erealloc(sockbuf->readbuf, sockbuf->readbuflen); - } + return nr_read; +} + +int _php3_sock_set_blocking(int socket, int mode) +{ + int old; + SOCK_FIND(sock, socket); + + old = sock->is_blocked; + + sock->is_blocked = mode; + + return old; +} + +#define SOCK_FIND_AND_READ \ + SOCK_FIND(sock,socket); \ + _php3_sock_read(sock) + +#define SOCK_FIND_AND_READ_MAX(max) \ + SOCK_FIND(sock, socket); \ + if(sock->is_blocked) _php3_sock_read_limited(sock, max); else _php3_sock_read(sock) + +/* + * FIXME: fgets depends on '\n' as line delimiters + */ + +char *_php3_sock_fgets(char *buf, size_t maxlen, int socket) +{ + char *p = NULL; + char *ret = NULL; + size_t amount = 0; + size_t nr_read; + SOCK_FIND_AND_READ_MAX(1); + + if(maxlen < 0) return ret; + + if(sock->is_blocked) { + for(nr_read = 1; !sock->eof && nr_read < maxlen; ) { + nr_read += _php3_sock_read_limited(sock, 1); + if((p = memchr(READPTR(sock), '\n', TOREAD(sock))) != NULL) break; } - memcpy(sockbuf->readbuf + sockbuf->writepos, buf, buflen); - sockbuf->writepos += buflen; + } else { + p = memchr(READPTR(sock), '\n', MIN(TOREAD(sock), maxlen - 1)); + } + + if(p) { + amount = (ptrdiff_t) p - (ptrdiff_t) READPTR(sock) + 1; + } else { + amount = MIN(TOREAD(sock), maxlen - 1); + } + + if(amount > 0) { + memcpy(buf, READPTR(sock), amount); + sock->readpos += amount; } + buf[amount] = '\0'; + + /* signal error only, if we don't return data from this call and + if there is no data to read and if the eof flag is set */ + if(amount || TOREAD(sock) || !sock->eof) + ret = buf; - sock_fgets_exit: - *buf = '\0'; - return count; + return ret; } -/* }}} */ -/* {{{ _php3_sock_fread() */ +/* + * FIXME: fgetc returns EOF, if no data is available on a nonblocking socket. + * I don't have any documentation on the semantics of fgetc in this case. + * + * ss@2ns.de 19990528 + */ -int _php3_sock_fread(char *buf, int maxlen, int socket) +int _php3_sock_fgetc(int socket) { - struct php3i_sockbuf *sockbuf = phpsockbuf; - int bytesread, toread, count = 0; - - while (sockbuf) { - if (sockbuf->socket == socket) { - toread = sockbuf->writepos - sockbuf->readpos; - if (toread > maxlen) { - toread = maxlen; - } - memcpy(buf, sockbuf->readbuf + sockbuf->readpos, toread); - sockbuf->readpos += toread; - count += toread; - buf += toread; - break; - } - sockbuf = sockbuf->next; + int ret = EOF; + SOCK_FIND_AND_READ_MAX(1); + + if(TOREAD(sock) > 0) { + ret = *READPTR(sock); + sock->readpos++; } - while (count < maxlen) { - toread = maxlen - count; - bytesread = recv(socket, buf, toread, 0); - if (bytesread <= 0) { - break; - } - count += bytesread; - buf += bytesread; + return ret; +} + +int _php3_sock_feof(int socket) +{ + int ret = 0; + SOCK_FIND_AND_READ_MAX(1); + + if(!TOREAD(sock) && sock->eof) + ret = 1; + + return ret; +} + +size_t _php3_sock_fread(char *ptr, size_t size, int socket) +{ + size_t ret = 0; + SOCK_FIND_AND_READ_MAX(size); + + if(size < 0) return ret; + + ret = MIN(TOREAD(sock), size); + if(ret) { + memcpy(ptr, READPTR(sock), ret); + sock->readpos += ret; } - *buf = '\0'; - return count; + return ret; } -/* }}} */ + /* {{{ module start/shutdown functions */ /* {{{ _php3_sock_destroy */ -#ifndef THREAD_SAFE -static void _php3_sock_destroy(void *data) +static void _php3_msock_destroy(int *data) { - int *sock = (int *) data; - close(*sock); + close(*data); } -#endif /* }}} */ /* {{{ php3_minit_fsock */ @@ -453,7 +639,7 @@ static int php3_minit_fsock(INIT_FUNC_ARGS) { #ifndef THREAD_SAFE _php3_hash_init(&ht_keys, 0, NULL, NULL, 1); - _php3_hash_init(&ht_socks, 0, NULL, _php3_sock_destroy, 1); + _php3_hash_init(&ht_socks, 0, NULL, (void (*)(void *))_php3_msock_destroy, 1); #endif return SUCCESS; } @@ -466,6 +652,7 @@ static int php3_mshutdown_fsock(SHUTDOWN_FUNC_ARGS) _php3_hash_destroy(&ht_socks); _php3_hash_destroy(&ht_keys); #endif + php_cleanup_sockbuf(1); return SUCCESS; } /* }}} */ @@ -473,15 +660,7 @@ static int php3_mshutdown_fsock(SHUTDOWN_FUNC_ARGS) static int php3_rshutdown_fsock(SHUTDOWN_FUNC_ARGS) { - struct php3i_sockbuf *sockbuf = phpsockbuf, *this; - - while (sockbuf) { - this = sockbuf; - sockbuf = this->next; - efree(this->readbuf); - efree(this); - } - phpsockbuf = NULL; + php_cleanup_sockbuf(0); return SUCCESS; } diff --git a/ext/standard/fsock.h b/ext/standard/fsock.h index a4a01b1bf9..1b2c7e851c 100644 --- a/ext/standard/fsock.h +++ b/ext/standard/fsock.h @@ -32,29 +32,21 @@ #ifndef _FSOCK_H #define _FSOCK_H -#if WIN32|WINNT -# ifndef WINNT -# define WINNT 1 -# endif -#undef FD_SETSIZE -#include "arpa/inet.h" -#endif - -#if HAVE_NETINET_IN_H -#include -#endif - extern php3_module_entry fsock_module_entry; #define fsock_module_ptr &fsock_module_entry PHP_FUNCTION(fsockopen); PHP_FUNCTION(pfsockopen); -extern int lookup_hostname(const char *addr, struct in_addr *in); -extern int _php3_sock_fgets(char *buf, int maxlen, int socket); -extern int _php3_sock_fread(char *buf, int maxlen, int socket); -extern int _php3_is_persistent_sock(int); -int _php3_sock_eof(int socket); +int lookup_hostname(const char *addr, struct in_addr *in); +char *_php3_sock_fgets(char *buf, size_t maxlen, int socket); +size_t _php3_sock_fread(char *buf, size_t maxlen, int socket); +int _php3_sock_feof(int socket); +int _php3_sock_fgetc(int socket); +int _php3_is_persistent_sock(int); +int _php3_sock_set_blocking(int socket, int mode); +int _php3_sock_destroy(int socket); +int _php3_sock_close(int socket); -#define phpext_fsock_ptr fsock_module_ptr +PHPAPI int connect_nonb(int sockfd, struct sockaddr *addr, int addrlen, struct timeval *timeout); #endif /* _FSOCK_H */ diff --git a/ext/standard/php3_string.h b/ext/standard/php3_string.h index 221c8e72d7..0de055e0bc 100644 --- a/ext/standard/php3_string.h +++ b/ext/standard/php3_string.h @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP HTML Embedded Scripting Language Version 3.0 | +----------------------------------------------------------------------+ - | Copyright (c) 1997,1998 PHP Development Team (See Credits file) | + | Copyright (c) 1997-1999 PHP Development Team (See Credits file) | +----------------------------------------------------------------------+ | This program is free software; you can redistribute it and/or modify | | it under the terms of one of the following licenses: | @@ -24,7 +24,7 @@ | contact core@php.net. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf | - | Stig Sæther Bakken | + | Stig Sæther Bakken | +----------------------------------------------------------------------+ */ @@ -47,7 +47,8 @@ PHP_FUNCTION(str_replace); PHP_FUNCTION(chop); PHP_FUNCTION(trim); PHP_FUNCTION(ltrim); -void soundex(INTERNAL_FUNCTION_PARAMETERS); +PHP_FUNCTION(similar_text); +extern void soundex(INTERNAL_FUNCTION_PARAMETERS); PHP_FUNCTION(explode); PHP_FUNCTION(implode); @@ -78,15 +79,30 @@ PHP_FUNCTION(newline_to_br); PHP_FUNCTION(setlocale); PHP_FUNCTION(stristr); PHP_FUNCTION(chunk_split); +PHP_FUNCTION(strip_tags); PHP_FUNCTION(parsestr); PHP_FUNCTION(bin2hex); +#if HAVE_CRYPT +extern php3_module_entry crypt_module_entry; +#define crypt_module_ptr &crypt_module_entry +PHP_FUNCTION(crypt); +extern int php3_minit_crypt(INIT_FUNC_ARGS); +#else +#define crypt_module_ptr NULL +#endif + extern PHPAPI char *_php3_strtoupper(char *s); extern PHPAPI char *_php3_strtolower(char *s); -extern char *_StrTr(char *string, char *str_from, char *str_to); +extern PHPAPI char *_php3_strtr(char *string, int len, char *str_from, char *str_to, int trlen); extern PHPAPI char *_php3_addslashes(char *string, int length, int *new_length, int freeit); extern PHPAPI void _php3_stripslashes(char *string, int *len); extern PHPAPI void _php3_dirname(char *str, int len); extern PHPAPI char *php3i_stristr(unsigned char *s, unsigned char *t); +extern PHPAPI void _php3_trim(pval *str, pval * return_value); +extern PHPAPI void _php3_strip_tags(char *rbuf, int state); +extern PHPAPI void _php3_char_to_str(char *str,uint len,char from,char *to,int to_len,pval *result); +extern PHPAPI void _php3_implode(pval *delim, pval *arr, pval *return_value); +extern PHPAPI void _php3_explode(pval *delim, pval *str, pval *return_value); #endif /* _PHPSTRING_H */ diff --git a/ext/standard/string.c b/ext/standard/string.c index bfc66735a9..9f29036eb7 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP HTML Embedded Scripting Language Version 3.0 | +----------------------------------------------------------------------+ - | Copyright (c) 1997,1998 PHP Development Team (See Credits file) | + | Copyright (c) 1997-1999 PHP Development Team (See Credits file) | +----------------------------------------------------------------------+ | This program is free software; you can redistribute it and/or modify | | it under the terms of one of the following licenses: | @@ -24,24 +24,20 @@ | contact core@php.net. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf | - | Stig Sæther Bakken | + | Stig Sæther Bakken | | Zeev Suraski | +----------------------------------------------------------------------+ */ - /* $Id$ */ #include #include "php.h" -#include "reg.h" -#include "post.h" -#include "php3_string.h" +#include "php_globals.h" +#include "php3_standard.h" #if HAVE_SETLOCALE #include #endif -#include "zend_execute.h" -#include "php_globals.h" static char hexconvtab[] = "0123456789abcdef"; @@ -88,11 +84,13 @@ PHP_FUNCTION(bin2hex) RETURN_STRINGL(new, newlen, 0); } + /* {{{ proto int strlen(string str) Get string length */ -PHP_FUNCTION(strlen) +void php3_strlen(INTERNAL_FUNCTION_PARAMETERS) { pval *str; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &str) == FAILURE) { WRONG_PARAM_COUNT; @@ -104,7 +102,7 @@ PHP_FUNCTION(strlen) /* {{{ proto int strcmp(string str1, string str2) Binary safe string comparison */ -PHP_FUNCTION(strcmp) +void php3_strcmp(INTERNAL_FUNCTION_PARAMETERS) { pval *s1,*s2; @@ -119,7 +117,7 @@ PHP_FUNCTION(strcmp) /* {{{ proto int strcasecmp(string str1, string str2) Binary safe case-insensitive string comparison */ -PHP_FUNCTION(strcasecmp) +void php3_strcasecmp(INTERNAL_FUNCTION_PARAMETERS) { pval *s1,*s2; @@ -128,13 +126,13 @@ PHP_FUNCTION(strcasecmp) } convert_to_string(s1); convert_to_string(s2); - RETURN_LONG(strcasecmp(s1->value.str.val,s2->value.str.val)); + RETURN_LONG(zend_binary_strcasecmp(s1,s2)); } /* }}} */ /* {{{ proto int strspn(string str, string mask) Find length of initial segment consisting entirely of characters found in mask */ -PHP_FUNCTION(strspn) +void php3_strspn(INTERNAL_FUNCTION_PARAMETERS) { pval *s1,*s2; @@ -149,7 +147,7 @@ PHP_FUNCTION(strspn) /* {{{ proto int strcspn(string str, string mask) Find length of initial segment consisting entirely of characters not found in mask */ -PHP_FUNCTION(strcspn) +void php3_strcspn(INTERNAL_FUNCTION_PARAMETERS) { pval *s1,*s2; @@ -162,12 +160,17 @@ PHP_FUNCTION(strcspn) } /* }}} */ +/* {{{ proto string rtrim(string str) + An alias for chop */ +/* }}} */ + /* {{{ proto string chop(string str) Remove trailing whitespace */ -PHP_FUNCTION(chop) +void php3_chop(INTERNAL_FUNCTION_PARAMETERS) { pval *str; register int i; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &str) == FAILURE) { WRONG_PARAM_COUNT; @@ -192,12 +195,41 @@ PHP_FUNCTION(chop) } /* }}} */ +PHPAPI void _php3_trim(pval *str, pval * return_value) +{ + register int i; + + int len = str->value.str.len; + int trimmed = 0; + char *c = str->value.str.val; + for (i = 0; i < len; i++) { + if (c[i] == ' ' || c[i] == '\n' || c[i] == '\r' || + c[i] == '\t' || c[i] == '\v') { + trimmed++; + } else { + break; + } + } + len-=trimmed; + c+=trimmed; + for (i = len - 1; i >= 0; i--) { + if (c[i] == ' ' || c[i] == '\n' || c[i] == '\r' || + c[i] == '\t' || c[i] == '\v') { + len--; + } else { + break; + } + } + RETVAL_STRINGL(c, len, 1); +} + /* {{{ proto string trim(string str) Strip whitespace from the beginning and end of a string */ -PHP_FUNCTION(trim) +void php3_trim(INTERNAL_FUNCTION_PARAMETERS) { pval *str; register int i; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &str) == FAILURE) { WRONG_PARAM_COUNT; @@ -235,57 +267,28 @@ PHP_FUNCTION(trim) /* {{{ proto string ltrim(string str) Strip whitespace from the beginning of a string */ -PHP_FUNCTION(ltrim) +void php3_ltrim(INTERNAL_FUNCTION_PARAMETERS) { pval *str; - register int i; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &str) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string(str); - if (str->type == IS_STRING) { - int len = str->value.str.len; - int trimmed = 0; - char *c = str->value.str.val; - for (i = 0; i < len; i++) { - if (c[i] == ' ' || c[i] == '\n' || c[i] == '\r' || - c[i] == '\t' || c[i] == '\v') { - trimmed++; - } else { - break; - } - } - RETVAL_STRINGL(c+trimmed, len-trimmed, 1); + _php3_trim(str, return_value); return; } RETURN_FALSE; } /* }}} */ -/* {{{ proto array(string separator, string str) - Split a string on string separator and return array of components */ -PHP_FUNCTION(explode) +void _php3_explode(pval *delim, pval *str, pval *return_value) { - pval *str, *delim; char *work_str, *p1, *p2; int i = 0; - if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &delim, &str) == FAILURE) { - WRONG_PARAM_COUNT; - } - convert_to_string(str); - convert_to_string(delim); - - if (strlen(delim->value.str.val)==0) { - /* the delimiter must be a valid C string that's at least 1 character long */ - php3_error(E_WARNING,"Empty delimiter"); - RETURN_FALSE; - } - if (array_init(return_value) == FAILURE) { - return; - } work_str = p1 = estrndup(str->value.str.val,str->value.str.len); p2 = strstr(p1, delim->value.str.val); if (p2 == NULL) { @@ -300,38 +303,47 @@ PHP_FUNCTION(explode) } efree(work_str); } -/* }}} */ -/* {{{ proto string implode(array src, string glue) - Join array elements placing glue string between items and return one string */ -PHP_FUNCTION(implode) +/* {{{ proto array explode(string separator, string str) + Split a string on string separator and return array of components */ +void php3_explode(INTERNAL_FUNCTION_PARAMETERS) { - pval *arg1, *arg2, *delim, **tmp, *arr; - int len = 0, count = 0; - - if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + pval *str, *delim; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &delim, &str) == FAILURE) { WRONG_PARAM_COUNT; } + convert_to_string(str); + convert_to_string(delim); + + if (strlen(delim->value.str.val)==0) { + /* the delimiter must be a valid C string that's at least 1 character long */ + php3_error(E_WARNING,"Empty delimiter"); + RETURN_FALSE; + } - if (arg1->type == IS_ARRAY && arg2->type == IS_STRING) { - arr = arg1; - delim = arg2; - } else if (arg2->type == IS_ARRAY) { - convert_to_string(arg1); - arr = arg2; - delim = arg1; - } else { - php3_error(E_WARNING, "Bad arguments to %s()", - get_active_function_name()); + if (array_init(return_value) == FAILURE) { return; } + _php3_explode(delim, str, return_value); +} +/* }}} */ + +/* {{{ proto string join(array src, string glue) + An alias for implode */ +/* }}} */ +void _php3_implode(pval *delim, pval *arr, pval *return_value) +{ + pval *tmp; + int len = 0, count = 0; + PLS_FETCH(); /* convert everything to strings, and calculate length */ _php3_hash_internal_pointer_reset(arr->value.ht); while (_php3_hash_get_current_data(arr->value.ht, (void **) &tmp) == SUCCESS) { - convert_to_string(*tmp); - if ((*tmp)->type == IS_STRING) { - len += (*tmp)->value.str.len; + convert_to_string(tmp); + if (tmp->type == IS_STRING && tmp->value.str.val != undefined_variable_string) { + len += tmp->value.str.len; if (count>0) { len += delim->value.str.len; } @@ -346,9 +358,9 @@ PHP_FUNCTION(implode) return_value->value.str.val[len] = '\0'; _php3_hash_internal_pointer_reset(arr->value.ht); while (_php3_hash_get_current_data(arr->value.ht, (void **) &tmp) == SUCCESS) { - if ((*tmp)->type == IS_STRING) { + if (tmp->type == IS_STRING && tmp->value.str.val != undefined_variable_string) { count--; - strcat(return_value->value.str.val, (*tmp)->value.str.val); + strcat(return_value->value.str.val, tmp->value.str.val); if (count > 0) { strcat(return_value->value.str.val, delim->value.str.val); } @@ -356,19 +368,44 @@ PHP_FUNCTION(implode) _php3_hash_move_forward(arr->value.ht); } return_value->type = IS_STRING; - return_value->refcount = 1; - return_value->is_ref = 0; return_value->value.str.len = len; } + + +/* {{{ proto string implode(array src, string glue) + Join array elements placing glue string between items and return one string */ +void php3_implode(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *arg1, *arg2, *delim, *arr; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + + if (arg1->type == IS_ARRAY && arg2->type == IS_STRING) { + arr = arg1; + delim = arg2; + } else if (arg2->type == IS_ARRAY) { + convert_to_string(arg1); + arr = arg2; + delim = arg1; + } else { + php3_error(E_WARNING, "Bad arguments to %s()", + get_active_function_name()); + return; + } + _php3_implode(delim, arr, return_value) ; +} /* }}} */ + #ifndef THREAD_SAFE char *strtok_string; #endif /* {{{ proto string strtok([string str,] string token) Tokenize a string */ -PHP_FUNCTION(strtok) +void php3_strtok(INTERNAL_FUNCTION_PARAMETERS) { pval *str, *tok; #ifndef THREAD_SAFE @@ -378,6 +415,7 @@ PHP_FUNCTION(strtok) char *token = NULL, *tokp=NULL; char *first = NULL; int argc; + PLS_FETCH(); argc = ARG_COUNT(ht); @@ -409,7 +447,7 @@ PHP_FUNCTION(strtok) if (strtok_pos2) { *strtok_pos2 = '\0'; } - RETVAL_STRING(strtok_pos1,1); + RETVAL_STRING(strtok_pos1, 1); #if 0 /* skip 'token' white space for next call to strtok */ while (strtok_pos2 && @@ -442,10 +480,11 @@ PHPAPI char *_php3_strtoupper(char *s) /* {{{ proto string strtoupper(string str) Make a string uppercase */ -PHP_FUNCTION(strtoupper) +void php3_strtoupper(INTERNAL_FUNCTION_PARAMETERS) { pval *arg; char *ret; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg)) { WRONG_PARAM_COUNT; @@ -473,10 +512,11 @@ PHPAPI char *_php3_strtolower(char *s) /* {{{ proto string strtolower(string str) Make a string lowercase */ -PHP_FUNCTION(strtolower) +void php3_strtolower(INTERNAL_FUNCTION_PARAMETERS) { pval *str; char *ret; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &str)) { WRONG_PARAM_COUNT; @@ -490,10 +530,11 @@ PHP_FUNCTION(strtolower) /* {{{ proto string basename(string path) Return the filename component of the path */ -PHP_FUNCTION(basename) +void php3_basename(INTERNAL_FUNCTION_PARAMETERS) { pval *str; char *ret, *c; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &str)) { WRONG_PARAM_COUNT; @@ -542,10 +583,11 @@ PHPAPI void _php3_dirname(char *str, int len) { /* {{{ proto string dirname(string path) Return the directory name component of the path */ -PHP_FUNCTION(dirname) +void php3_dirname(INTERNAL_FUNCTION_PARAMETERS) { pval *str; char *ret; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &str)) { WRONG_PARAM_COUNT; @@ -559,7 +601,7 @@ PHP_FUNCTION(dirname) /* }}} */ -/* case-insensitve strstr */ +/* case insensitive strstr */ PHPAPI char *php3i_stristr(unsigned char *s, unsigned char *t) { int i, j, k, l; @@ -574,12 +616,13 @@ PHPAPI char *php3i_stristr(unsigned char *s, unsigned char *t) return NULL; } -/* {{{ proto string strstr(string haystack, string needle) +/* {{{ proto string stristr(string haystack, string needle) Find first occurrence of a string within another, case insensitive */ -PHP_FUNCTION(stristr) +void php3_stristr(INTERNAL_FUNCTION_PARAMETERS) { pval *haystack, *needle; char *found = NULL; + PLS_FETCH(); if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &haystack, &needle) == FAILURE) { @@ -602,12 +645,17 @@ PHP_FUNCTION(stristr) } /* }}} */ +/* {{{ proto string strchr(string haystack, string needle) + An alias for strstr */ +/* }}} */ + /* {{{ proto string strstr(string haystack, string needle) Find first occurrence of a string within another */ -PHP_FUNCTION(strstr) +void php3_strstr(INTERNAL_FUNCTION_PARAMETERS) { pval *haystack, *needle; char *found = NULL; + PLS_FETCH(); if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &haystack, &needle) == FAILURE) { @@ -635,13 +683,14 @@ PHP_FUNCTION(strstr) } /* }}} */ -/* {{{ proto int strpos(string haystack, string needle) +/* {{{ proto int strpos(string haystack, string needle [, int offset]) Find position of first occurrence of a string within another */ -PHP_FUNCTION(strpos) +void php3_strpos(INTERNAL_FUNCTION_PARAMETERS) { pval *haystack, *needle, *OFFSET; int offset = 0; char *found = NULL; + PLS_FETCH(); switch(ARG_COUNT(ht)) { case 2: @@ -686,10 +735,11 @@ PHP_FUNCTION(strpos) /* {{{ proto int strrpos(string haystack, string needle) Find the last occurrence of a character in a string within another */ -PHP_FUNCTION(strrpos) +void php3_strrpos(INTERNAL_FUNCTION_PARAMETERS) { pval *haystack, *needle; char *found = NULL; + PLS_FETCH(); if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &haystack, &needle) == FAILURE) { WRONG_PARAM_COUNT; @@ -713,10 +763,11 @@ PHP_FUNCTION(strrpos) /* {{{ proto string strrchr(string haystack, string needle) Find the last occurrence of a character in a string within another */ -PHP_FUNCTION(strrchr) +void php3_strrchr(INTERNAL_FUNCTION_PARAMETERS) { pval *haystack, *needle; char *found = NULL; + PLS_FETCH(); if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &haystack, &needle) == FAILURE) { @@ -742,7 +793,8 @@ PHP_FUNCTION(strrchr) /* }}} */ static char * -_php3_chunk_split(char *src, int srclen, char *end, int endlen, int chunklen) +_php3_chunk_split(char *src, int srclen, char *end, int endlen, + int chunklen, int *destlen) { char *dest; char *p, *q; @@ -770,13 +822,14 @@ _php3_chunk_split(char *src, int srclen, char *end, int endlen, int chunklen) } *q = '\0'; + if(destlen) *destlen = q - dest; return(dest); } /* {{{ proto string chunk_split(string str [, int chunklen [, string ending]]) Return split line */ -PHP_FUNCTION(chunk_split) +void php3_chunk_split(INTERNAL_FUNCTION_PARAMETERS) { pval *p_str, *p_chunklen, *p_ending; int argc; @@ -784,13 +837,13 @@ PHP_FUNCTION(chunk_split) char *end = "\r\n"; int endlen = 2; int chunklen = 76; + int result_len; + PLS_FETCH(); argc = ARG_COUNT(ht); - - if(!((argc == 1 && getParameters(ht, 1, &p_str) != FAILURE) || - (argc == 2 && getParameters(ht, 2, &p_str, &p_chunklen) != FAILURE) || - (argc == 3 && getParameters(ht, 3, &p_str, &p_chunklen, - &p_ending) != FAILURE))) { + + if(argc < 1 || argc > 3 || getParameters(ht, argc, &p_str, + &p_chunklen, &p_ending) == FAILURE) { WRONG_PARAM_COUNT; } @@ -812,10 +865,10 @@ PHP_FUNCTION(chunk_split) } result = _php3_chunk_split(p_str->value.str.val, p_str->value.str.len, - end, endlen, chunklen); + end, endlen, chunklen, &result_len); if(result) { - RETVAL_STRING(result, 0); + RETVAL_STRINGL(result, result_len, 0); } else { RETURN_FALSE; } @@ -824,11 +877,12 @@ PHP_FUNCTION(chunk_split) /* {{{ proto string substr(string str, int start [, int length]) Return part of a string */ -PHP_FUNCTION(substr) +void php3_substr(INTERNAL_FUNCTION_PARAMETERS) { pval *string, *from, *len; int argc, l; int f; + PLS_FETCH(); argc = ARG_COUNT(ht); @@ -872,22 +926,23 @@ PHP_FUNCTION(substr) RETURN_FALSE; } + /* Adjust l to match the actual string segment to be returned */ if((f+l) > (int)string->value.str.len) { l = (int)string->value.str.len - f; } - - RETVAL_STRINGL(string->value.str.val + f, l, 1); + RETVAL_STRINGL(string->value.str.val + f,l,1); } /* }}} */ /* {{{ proto string quotemeta(string str) Quote meta characters */ -PHP_FUNCTION(quotemeta) +void php3_quotemeta(INTERNAL_FUNCTION_PARAMETERS) { pval *arg; char *str, *old; char *p, *q; char c; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg) == FAILURE) { WRONG_PARAM_COUNT; @@ -928,9 +983,10 @@ PHP_FUNCTION(quotemeta) /* {{{ proto int ord(string character) Return ASCII value of character */ -PHP_FUNCTION(ord) +void php3_ord(INTERNAL_FUNCTION_PARAMETERS) { pval *str; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &str) == FAILURE) { WRONG_PARAM_COUNT; @@ -942,10 +998,11 @@ PHP_FUNCTION(ord) /* {{{ proto string chr(int ascii) Convert ASCII code to a character */ -PHP_FUNCTION(chr) +void php3_chr(INTERNAL_FUNCTION_PARAMETERS) { pval *num; char temp[2]; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &num) == FAILURE) { WRONG_PARAM_COUNT; @@ -957,9 +1014,9 @@ PHP_FUNCTION(chr) } /* }}} */ -/* {{{ proto string(string str) +/* {{{ proto string ucfirst(string str) Make a string's first character uppercase */ -PHP_FUNCTION(ucfirst) +void php3_ucfirst(INTERNAL_FUNCTION_PARAMETERS) { pval *arg; @@ -978,7 +1035,7 @@ PHP_FUNCTION(ucfirst) /* {{{ proto string ucwords(string str) Uppercase the first character of every word in a string */ -PHP_FUNCTION(ucwords) +void php3_ucwords(INTERNAL_FUNCTION_PARAMETERS) { pval *arg; char *r; @@ -1003,14 +1060,33 @@ PHP_FUNCTION(ucwords) } /* }}} */ +PHPAPI char *_php3_strtr(char *string, int len, char *str_from, char *str_to, int trlen) +{ + int i; + unsigned char xlat[256]; + + if ((trlen < 1) || (len < 1)) + return string; + + for (i = 0; i < 256; xlat[i] = i, i++); + + for (i = 0; i < trlen; i++) { + xlat[(unsigned char) str_from[i]] = str_to[i]; + } + + for (i = 0; i < len; i++) { + string[i] = xlat[(unsigned char) string[i]]; + } + + return string; +} + /* {{{ proto string strtr(string str, string from, string to) Translate characters in str using given translation tables */ -PHP_FUNCTION(strtr) +void php3_strtr(INTERNAL_FUNCTION_PARAMETERS) { /* strtr(STRING,FROM,TO) */ pval *str, *from, *to; - unsigned char xlat[256]; - unsigned char *str_from, *str_to, *string; - int i, len1, len2; + PLS_FETCH(); if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &str, &from, &to) == FAILURE) { @@ -1020,35 +1096,19 @@ PHP_FUNCTION(strtr) convert_to_string(from); convert_to_string(to); - string = (unsigned char*) str->value.str.val; - str_from = (unsigned char*) from->value.str.val; - str_to = (unsigned char*) to->value.str.val; - - len1 = from->value.str.len; - len2 = to->value.str.len; - - if (len1 > len2) { - str_from[len2] = '\0'; - len1 = len2; - } - for (i = 0; i < 256; xlat[i] = i, i++); - - for (i = 0; i < len1; i++) { - xlat[(unsigned char) str_from[i]] = str_to[i]; - } - - for (i = 0; i < str->value.str.len; i++) { - string[i] = xlat[(unsigned char) string[i]]; - } - - RETVAL_STRING((char *)string,1); + RETVAL_STRING(_php3_strtr(str->value.str.val, + str->value.str.len, + from->value.str.val, + to->value.str.val, + MIN(from->value.str.len,to->value.str.len)), + 1); } /* }}} */ /* {{{ proto string strrev(string str) Reverse a string */ -PHP_FUNCTION(strrev) +void php3_strrev(INTERNAL_FUNCTION_PARAMETERS) { pval *str; int i,len; @@ -1073,14 +1133,87 @@ PHP_FUNCTION(strrev) } /* }}} */ +static void _php3_similar_str(const char *txt1, int len1, const char *txt2, + int len2, int *pos1, int *pos2, int *max) +{ + char *p, *q; + char *end1 = (char *) txt1 + len1; + char *end2 = (char *) txt2 + len2; + int l; + + *max = 0; + for (p = (char *) txt1; p < end1; p++) { + for (q = (char *) txt2; q < end2; q++) { + for (l = 0; (p + l < end1) && (q + l < end2) && (p[l] == q[l]); + l++); + if (l > *max) { + *max = l; + *pos1 = p - txt1; + *pos2 = q - txt2; + } + } + } +} + +static int _php3_similar_char(const char *txt1, int len1, + const char *txt2, int len2) +{ + int sum; + int pos1, pos2, max; + + _php3_similar_str(txt1, len1, txt2, len2, &pos1, &pos2, &max); + if ((sum = max)) { + if (pos1 && pos2) + sum += _php3_similar_char(txt1, pos1, txt2, pos2); + if ((pos1 + max < len1) && (pos2 + max < len2)) + sum += _php3_similar_char(txt1 + pos1 + max, len1 - pos1 - max, + txt2 + pos2 + max, len2 - pos2 -max); + } + return sum; +} +/* {{{ proto int similar_text(string str1, string str2 [, double percent]) + Calculates the similarity between two strings */ +void php3_similar_text(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *t1, *t2, *percent; + int ac = ARG_COUNT(ht); + int sim; + + if (ac < 2 || ac > 3 || + getParameters(ht, ac, &t1, &t2, &percent) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_string(t1); + convert_to_string(t2); + if(ac > 2) { + convert_to_double(percent); + } + + if((t1->value.str.len + t2->value.str.len) == 0) { + if(ac > 2) + percent->value.dval = 0; + RETURN_LONG(0); + } + + sim = _php3_similar_char(t1->value.str.val, t1->value.str.len, + t2->value.str.val, t2->value.str.len); + + if (ac > 2) { + percent->value.dval = sim * 200.0 / (t1->value.str.len + t2->value.str.len); + } + + RETURN_LONG(sim); +} +/* }}} */ + /* be careful, this edits the string in-place */ PHPAPI void _php3_stripslashes(char *string, int *len) { char *s, *t; int l; char escape_char='\\'; - PLS_FETCH(); if (PG(magic_quotes_sybase)) { escape_char='\''; @@ -1125,7 +1258,7 @@ PHPAPI void _php3_stripslashes(char *string, int *len) /* {{{ proto string addslashes(string str) Escape single quote, double quotes and backslash characters in a string with backslashes */ -PHP_FUNCTION(addslashes) +void php3_addslashes(INTERNAL_FUNCTION_PARAMETERS) { pval *str; @@ -1140,9 +1273,10 @@ PHP_FUNCTION(addslashes) /* {{{ proto string stripslashes(string str) Strip backslashes from a string */ -PHP_FUNCTION(stripslashes) +void php3_stripslashes(INTERNAL_FUNCTION_PARAMETERS) { pval *str; + PLS_FETCH(); if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &str) == FAILURE) { WRONG_PARAM_COUNT; @@ -1180,7 +1314,6 @@ PHPAPI char *_php3_addslashes(char *str, int length, int *new_length, int should char *source,*target; char *end; char c; - PLS_FETCH(); for (source=str,end=source+length,target=new_str; (c = *source) || source 981220 + */ + static char *_php3_str_to_str(char *haystack, int length, char *needle, int needle_len, char *str, int str_len, int *_new_length) { @@ -1328,22 +1466,79 @@ finish: return new; } +#else + +static char *_php3_memstr(char *s, char *c, size_t n, size_t m) +{ + char *p; + + for(p = s; (p - s) < n; p++) + if(memcmp(p, c, m) == 0) + return p; + return NULL; +} + +#define ATTCHSTR(st, sz) \ + nl += sz; \ + n = erealloc(n, nl + 1); \ + memcpy(n + no, st, sz); \ + no += sz + + +static char *_php3_str_to_str(char *a, int al, char *b, int bl, char *c, int cl, + int *newlen) +{ + char *n = NULL, *p, *q; + int nl = 0; + int no = 0; + + /* run through all occurences of b in a */ + for(p = q = a; (p = _php3_memstr(p, b, al - (p - a), bl)); q = p) { + /* attach everything between the previous occ. and this one */ + ATTCHSTR(q, p - q); + /* attach the replacement string c */ + ATTCHSTR(c, cl); + /* jump over string b in a */ + p += bl; + } + + /* anything left over ? */ + if((al - (q - a)) > 0) { + ATTCHSTR(q, al - (q - a)); + } + + if(newlen) *newlen = nl; + n[nl] = '\0'; + + return n; +} + +#undef ATTCHSTR +#endif + /* {{{ proto string str_replace(string needle, string str, string haystack) Replace all occurrences of needle in haystack with str */ -PHP_FUNCTION(str_replace) +void php3_str_replace(INTERNAL_FUNCTION_PARAMETERS) { pval *haystack, *needle, *str; char *new; int len = 0; - if(ARG_COUNT(ht) != 3 || + if(ARG_COUNT(ht) != 3 || getParameters(ht, 3, &needle, &str, &haystack) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string(haystack); convert_to_string(needle); - convert_to_string(str); if(needle->value.str.len == 1) { _php3_char_to_str(haystack->value.str.val,haystack->value.str.len,needle->value.str.val[0],str->value.str.val, str->value.str.len ,return_value); + convert_to_string(str); + + if(haystack->value.str.len == 0) { + RETURN_STRING(empty_string,1); + } + + if(needle->value.str.len == 1) { + _php3_char_to_str(haystack->value.str.val,haystack->value.str.len,needle->value.str.val[0],str->value.str.val, str->value.str.len ,return_value); return; } @@ -1352,10 +1547,10 @@ PHP_FUNCTION(str_replace) RETURN_FALSE; } - new = _php3_str_to_str(haystack->value.str.val, haystack->value.str.len, - needle->value.str.val, needle->value.str.len, - str->value.str.val, str->value.str.len, - &len); + new = _php3_str_to_str(haystack->value.str.val, haystack->value.str.len, + needle->value.str.val, needle->value.str.len, + str->value.str.val, str->value.str.len, + &len); RETURN_STRINGL(new, len, 0); } /* }}} */ @@ -1529,15 +1724,15 @@ static void _php3_hebrev(INTERNAL_FUNCTION_PARAMETERS,int convert_newlines) /* {{{ proto string hebrev(string str [, int max_chars_per_line]) Convert logical Hebrew text to visual text */ -PHP_FUNCTION(hebrev) +void php3_hebrev(INTERNAL_FUNCTION_PARAMETERS) { _php3_hebrev(INTERNAL_FUNCTION_PARAM_PASSTHRU,0); } /* }}} */ -/* {{{ proto string hebrev(string str [, int max_chars_per_line]) +/* {{{ proto string hebrevc(string str [, int max_chars_per_line]) Convert logical Hebrew text to visual text with newline conversion */ -PHP_FUNCTION(hebrev_with_conversion) +void php3_hebrev_with_conversion(INTERNAL_FUNCTION_PARAMETERS) { _php3_hebrev(INTERNAL_FUNCTION_PARAM_PASSTHRU,1); } @@ -1545,7 +1740,7 @@ PHP_FUNCTION(hebrev_with_conversion) /* {{{ proto string nl2br(string str) Converts newlines to HTML line breaks */ -PHP_FUNCTION(newline_to_br) +void php3_newline_to_br(INTERNAL_FUNCTION_PARAMETERS) { pval *str; @@ -1559,9 +1754,27 @@ PHP_FUNCTION(newline_to_br) } /* }}} */ +/* {{{ proto string strip_tags(string str) + Strips HTML and PHP tags from a string */ +void php3_strip_tags(INTERNAL_FUNCTION_PARAMETERS) +{ + char *buf; + pval *str; + + if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &str)==FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string(str); + buf=estrdup(str->value.str.val); + _php3_strip_tags(buf,0); + RETURN_STRING(buf,0); +} +/* }}} */ + + /* {{{ proto string setlocale(string category, string locale) Set locale information */ -PHP_FUNCTION(setlocale) +void php3_setlocale(INTERNAL_FUNCTION_PARAMETERS) { pval *category, *locale; int cat; @@ -1602,6 +1815,102 @@ PHP_FUNCTION(setlocale) } /* }}} */ +/* A simple little state-machine to strip out html and php tags + + State 0 is the output state, State 1 means we are inside a + normal html tag and state 2 means we are inside a php tag. + + The state variable is passed in to allow a function like fgetss + to maintain state across calls to the function. + + lc holds the last significant character read and br is a bracket + counter. +*/ +void _php3_strip_tags(char *rbuf, int state) { + char *buf, *p, *rp, c, lc; + int br; + + buf = estrdup(rbuf); + c = *buf; + lc = '\0'; + p = buf; + rp = rbuf; + br = 0; + + while (c) { /* This is not binary-safe. Don't see why it should be */ + switch (c) { + case '<': + if (state == 0) { + lc = '<'; + state = 1; + } + break; + + case '(': + if (state == 2) { + if (lc != '\"') { + lc = '('; + br++; + } + } else if (state == 0) { + *(rp++) = c; + } + break; + + case ')': + if (state == 2) { + if (lc != '\"') { + lc = ')'; + br--; + } + } else if (state == 0) { + *(rp++) = c; + } + break; + + case '>': + if (state == 1) { + lc = '>'; + state = 0; + } else if (state == 2) { + if (!br && lc != '\"' && *(p-1)=='?') { + state = 0; + } + } + break; + + case '\"': + if (state == 2) { + if (lc == '\"') { + lc = '\0'; + } else if (lc != '\\') { + lc = '\"'; + } + } else if (state == 0) { + *(rp++) = c; + } + break; + + case '?': + if (state==1 && *(p-1)=='<') { + br=0; + state=2; + break; + } + /* fall-through */ + + default: + if (state == 0) { + *(rp++) = c; + } + break; + } + c = *(++p); + } + *rp = '\0'; + efree(buf); +} + /* {{{ proto void parsestr(string encoded_string) Parses GET/POST/COOKIE data and sets global variables. */ PHP_FUNCTION(parsestr) @@ -1618,6 +1927,7 @@ PHP_FUNCTION(parsestr) } php3_treat_data(PARSE_STRING, res); } +/* }}} */ /* * Local variables: diff --git a/ext/standard/var.c b/ext/standard/var.c index 6965d5f9e0..53d4b8b0f0 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -491,7 +491,7 @@ PHP_FUNCTION(unserialize) } } -/* }}} * +/* }}} */ /* * Local variables: diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c index 2a563c6bc7..f8cc1be3a8 100644 --- a/main/fopen_wrappers.c +++ b/main/fopen_wrappers.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP HTML Embedded Scripting Language Version 3.0 | +----------------------------------------------------------------------+ - | Copyright (c) 1997,1998 PHP Development Team (See Credits file) | + | Copyright (c) 1997-1999 PHP Development Team (See Credits file) | +----------------------------------------------------------------------+ | This program is free software; you can redistribute it and/or modify | | it under the terms of one of the following licenses: | @@ -51,7 +51,6 @@ #include "safe_mode.h" #include "php3_realpath.h" -#include "ext/standard/head.h" #include "ext/standard/php3_standard.h" #include "zend_compile.h" @@ -88,97 +87,128 @@ #include #endif -static FILE *php3_fopen_url_wrapper(const char *path, char *mode, int options, int *issock, int *socketd); +static FILE *php3_fopen_url_wrapper(char *path, char *mode, int options, int *issock, int *socketd); int _php3_getftpresult(int socketd); + /* When open_basedir is not NULL, check if the given filename is located in open_basedir. Returns -1 if error or not in the open_basedir, else 0 When open_basedir is NULL, always return 0 */ -PHPAPI int _php3_check_open_basedir(char *path) +PHPAPI int _php3_check_specific_open_basedir(char *basedir, char *path) { char resolved_name[MAXPATHLEN]; + char resolved_basedir[MAXPATHLEN]; char local_open_basedir[MAXPATHLEN]; int local_open_basedir_pos; - PLS_FETCH(); - /* Only check when open_basedir is available */ - if (PG(open_basedir) && *PG(open_basedir)) { - - /* Special case basedir==".": Use script-directory */ - if ((strcmp(PG(open_basedir), ".") == 0) && - request_info.filename && - *request_info.filename + /* Special case basedir==".": Use script-directory */ + if ((strcmp(basedir, ".") == 0) && + request_info.filename && + *request_info.filename + ) { + strcpy(local_open_basedir, request_info.filename); + local_open_basedir_pos = strlen(local_open_basedir) - 1; + + /* Strip filename */ + while (( +#if WIN32|WINNT + (local_open_basedir[local_open_basedir_pos] != '\\') || +#endif + (local_open_basedir[local_open_basedir_pos] != '/') + ) && + (local_open_basedir_pos >= 0) ) { - strcpy(local_open_basedir, request_info.filename); - local_open_basedir_pos = strlen(local_open_basedir) - 1; - - /* Strip filename */ + local_open_basedir[local_open_basedir_pos--] = 0; + } +/* stripping unnecessary slashes is left + as an exercise to the underlying OS */ +#if 0 + /* Strip double (back)slashes */ + if (local_open_basedir_pos > 0) { while (( #if WIN32|WINNT - (local_open_basedir[local_open_basedir_pos] != '\\') || + (local_open_basedir[local_open_basedir_pos-1] == '\\') || #endif - (local_open_basedir[local_open_basedir_pos] != '/') + (local_open_basedir[local_open_basedir_pos-1] == '/') ) && - (local_open_basedir_pos >= 0) + (local_open_basedir_pos > 0) ) { local_open_basedir[local_open_basedir_pos--] = 0; } - -#if 0 - /* Strip double (back)slashes */ - if (local_open_basedir_pos > 0) { - while (( + } +#endif + } else { + /* Else use the unmodified path */ + strcpy(local_open_basedir, basedir); + } + + /* Resolve the real path into resolved_name */ + if ((_php3_realpath(path, resolved_name) != NULL) && (_php3_realpath(local_open_basedir, resolved_basedir) != NULL)) { + /* Check the path */ #if WIN32|WINNT - (local_open_basedir[local_open_basedir_pos-1] == '\\') || -#endif - (local_open_basedir[local_open_basedir_pos-1] == '/') - ) && - (local_open_basedir_pos > 0) - ) { - local_open_basedir[local_open_basedir_pos--] = 0; - } - } + if (strncasecmp(resolved_basedir, resolved_name, strlen(resolved_basedir)) == 0) { +#else + if (strncmp(resolved_basedir, resolved_name, strlen(resolved_basedir)) == 0) { #endif - + /* File is in the right directory */ + return 0; } else { - /* Else use the unmodified path */ - strcpy(local_open_basedir, PG(open_basedir)); + return -1; } - - /* Resolve the real path into resolved_name */ - if (_php3_realpath(path, resolved_name) != NULL) { - /* Check the path */ + } else { + /* Unable to resolve the real path, return -1 */ + return -1; + } +} + +PHPAPI int _php3_check_open_basedir(char *path) +{ + /* Only check when open_basedir is available */ + if (PG(open_basedir) && *PG(open_basedir)) { + char *pathbuf; + char *ptr; + char *end; + + pathbuf = estrdup(PG(open_basedir)); + + ptr = pathbuf; + + while (ptr && *ptr) { #if WIN32|WINNT - if (strncasecmp(local_open_basedir, resolved_name, strlen(local_open_basedir)) == 0) { + end = strchr(ptr, ';'); #else - if (strncmp(local_open_basedir, resolved_name, strlen(local_open_basedir)) == 0) { + end = strchr(ptr, ':'); #endif - /* File is in the right directory */ + if (end != NULL) { + *end = '\0'; + end++; + } + + if (_php3_check_specific_open_basedir(ptr, path) == 0) { + efree(pathbuf); return 0; - } else { - php3_error(E_WARNING, "open_basedir restriction in effect. File is in wrong directory."); - return -1; } - } else { - /* Unable to resolve the real path, return -1 */ - php3_error(E_WARNING, "open_basedir restriction in effect. Unable to verify location of file."); - return -1; + + ptr = end; } - } else { - /* open_basedir is not available, return 0 */ - return 0; + php3_error(E_WARNING, "open_basedir restriction in effect. File is in wrong directory."); + efree(pathbuf); + return -1; } + + /* Nothing to check... */ + return 0; } PHPAPI FILE *php3_fopen_wrapper(char *path, char *mode, int options, int *issock, int *socketd) { int cm=2; /* checkuid mode: 2 = if file does not exist, check directory */ - PLS_FETCH(); - + /* FIXME Lets not get in the habit of doing stuff like this. This should + be runtime enabled, NOT compile time. */ #if PHP3_URL_FOPEN if (!(options & IGNORE_URL)) { return php3_fopen_url_wrapper(path, mode, options, issock, socketd); @@ -199,17 +229,17 @@ PHPAPI FILE *php3_fopen_wrapper(char *path, char *mode, int options, int *issock #if CGI_BINARY || FHTTPD || USE_SAPI -PHPAPI FILE *php3_fopen_for_parser(void) +FILE *php3_fopen_for_parser(void) { FILE *fp; struct stat st; char *temp, *path_info, *fn; int l; PLS_FETCH(); - SLS_FETCH(); + fn = request_info.filename; - path_info = SG(request_info).request_uri; + path_info = request_info.path_info; #if HAVE_PWD_H if (PG(user_dir) && *PG(user_dir) && path_info && '/' == path_info[0] && '~' == path_info[1]) { @@ -280,17 +310,17 @@ PHPAPI FILE *php3_fopen_for_parser(void) fp = NULL; } if (!fp) { - php3_error(E_CORE_ERROR, "Unable to open %s", fn); + php3_error(E_ERROR, "Unable to open %s", fn); STR_FREE(request_info.filename); /* for same reason as above */ return NULL; } - - temp = estrdup(fn); + _php3_hash_index_update(&include_names, 0, (void *) &fn, sizeof(char *), NULL); + + temp = strdup(fn); _php3_dirname(temp, strlen(temp)); - if (*temp) { + if (*temp) chdir(temp); - } - efree(temp); + free(temp); return fp; } @@ -417,7 +447,7 @@ PHPAPI FILE *php3_fopen_with_path(char *filename, char *mode, char *path, char * * Otherwise, fopen is called as usual and the file pointer is returned. */ -static FILE *php3_fopen_url_wrapper(const char *path, char *mode, int options, int *issock, int *socketd) +static FILE *php3_fopen_url_wrapper(char *path, char *mode, int options, int *issock, int *socketd) { url *resource; int result; @@ -443,10 +473,9 @@ static FILE *php3_fopen_url_wrapper(const char *path, char *mode, int options, i FILE *fp = NULL; struct sockaddr_in server; unsigned short portno; - char winfeof; if (!strncasecmp(path, "http://", 7)) { - resource = url_parse((char *) path); + resource = url_parse(path); if (resource == NULL) { php3_error(E_WARNING, "Invalid URL specified, %s", path); *issock = BAD_URL; @@ -463,9 +492,9 @@ static FILE *php3_fopen_url_wrapper(const char *path, char *mode, int options, i free_url(resource); return NULL; } - lookup_hostname(resource->host, &server.sin_addr); + server.sin_family = AF_INET; - if (server.sin_addr.s_addr == -1) { + if (lookup_hostname(resource->host, &server.sin_addr)) { SOCK_FCLOSE(*socketd); *socketd = 0; free_url(resource); @@ -553,8 +582,8 @@ static FILE *php3_fopen_url_wrapper(const char *path, char *mode, int options, i /* Read past http header */ body = 0; location[0] = '\0'; - while (!body && recv(*socketd, (char *) &winfeof, 1, MSG_PEEK)) { - if (SOCK_FGETC(buf, *socketd) == SOCK_RECV_ERR) { + while (!body && !SOCK_FEOF(*socketd)) { + if ((buf[0] = SOCK_FGETC(*socketd)) == EOF) { SOCK_FCLOSE(*socketd); *socketd = 0; free_url(resource); @@ -606,7 +635,7 @@ static FILE *php3_fopen_url_wrapper(const char *path, char *mode, int options, i *issock = 1; return (fp); } else if (!strncasecmp(path, "ftp://", 6)) { - resource = url_parse((char *) path); + resource = url_parse(path); if (resource == NULL) { php3_error(E_WARNING, "Invalid URL specified, %s", path); *issock = BAD_URL; @@ -628,9 +657,9 @@ static FILE *php3_fopen_url_wrapper(const char *path, char *mode, int options, i free_url(resource); return NULL; } - lookup_hostname(resource->host, &server.sin_addr); + server.sin_family = AF_INET; - if (server.sin_addr.s_addr == -1) { + if (lookup_hostname(resource->host, &server.sin_addr)) { SOCK_FCLOSE(*socketd); *socketd = 0; free_url(resource); @@ -840,9 +869,9 @@ static FILE *php3_fopen_url_wrapper(const char *path, char *mode, int options, i free_url(resource); return NULL; } - lookup_hostname(resource->host, &server.sin_addr); + server.sin_family = AF_INET; - if (server.sin_addr.s_addr == -1) { + if (lookup_hostname(resource->host, &server.sin_addr)) { free_url(resource); SOCK_FCLOSE(*socketd); *socketd = 0; @@ -881,17 +910,15 @@ static FILE *php3_fopen_url_wrapper(const char *path, char *mode, int options, i return (fp); } else { - PLS_FETCH(); - if (options & USE_PATH) { - fp = php3_fopen_with_path((char *) path, mode, PG(include_path), NULL); + fp = php3_fopen_with_path(path, mode, PG(include_path), NULL); } else { int cm=2; if(!strcmp(mode,"r") || !strcmp(mode,"r+")) cm=0; if (options & ENFORCE_SAFE_MODE && PG(safe_mode) && (!_php3_checkuid(path, cm))) { fp = NULL; } else { - if (_php3_check_open_basedir((char *) path)) { + if (_php3_check_open_basedir(path)) { fp = NULL; } else { fp = fopen(path, mode); diff --git a/main/fopen_wrappers.h b/main/fopen_wrappers.h index c1e1420b3c..c078940e36 100644 --- a/main/fopen_wrappers.h +++ b/main/fopen_wrappers.h @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP HTML Embedded Scripting Language Version 3.0 | +----------------------------------------------------------------------+ - | Copyright (c) 1997,1998 PHP Development Team (See Credits file) | + | Copyright (c) 1997-1999 PHP Development Team (See Credits file) | +----------------------------------------------------------------------+ | This program is free software; you can redistribute it and/or modify | | it under the terms of one of the following licenses: | @@ -46,17 +46,18 @@ # define SOCK_ERR INVALID_SOCKET # define SOCK_CONN_ERR SOCKET_ERROR # define SOCK_RECV_ERR SOCKET_ERROR -# define SOCK_FCLOSE(s) closesocket(s) #else # define SOCK_ERR -1 # define SOCK_CONN_ERR -1 # define SOCK_RECV_ERR -1 -# define SOCK_FCLOSE(s) close(s) #endif #define SOCK_WRITE(d,s) send(s,d,strlen(d),0) #define SOCK_WRITEL(d,l,s) send(s,d,l,0) -#define SOCK_FGETC(c,s) recv(s,c,1,0) +#define SOCK_FGETC(s) _php3_sock_fgetc((s)) #define SOCK_FGETS(b,l,s) _php3_sock_fgets((b),(l),(s)) +#define SOCK_FEOF(sock) _php3_sock_feof((sock)) +#define SOCK_FREAD(ptr,size,sock) _php3_sock_fread((ptr),(size),(sock)) +#define SOCK_FCLOSE(s) _php3_sock_close(s) /* values for issock */ #define IS_NOT_SOCKET 0 @@ -69,15 +70,15 @@ extern int wsa_fp; /* a list for open sockets */ extern PHPAPI FILE *php3_fopen_wrapper(char *filename, char *mode, int options, int *issock, int *socketd); -PHPAPI FILE *php3_fopen_for_parser(void); +extern FILE *php3_fopen_for_parser(void); extern PHPAPI int _php3_check_open_basedir(char *path); +extern PHPAPI int _php3_check_specific_open_basedir(char *basedir, char *path); extern PHPAPI FILE *php3_fopen_with_path(char *filename, char *mode, char *path, char **opened_path); extern PHPAPI int php3_isurl(char *path); extern PHPAPI char *php3_strip_url_passwd(char *path); -extern PHPAPI int php3_write(void *buf, int size); extern PHPAPI char *expand_filepath(char *filepath); diff --git a/main/php_globals.h b/main/php_globals.h index 7dd5cf4002..1a947c3aed 100644 --- a/main/php_globals.h +++ b/main/php_globals.h @@ -29,13 +29,13 @@ struct _php_core_globals { long magic_quotes_runtime; long magic_quotes_sybase; - long asp_tags; - long short_tags; + long asp_tags; + long short_tags; - long safe_mode; - long sql_safe_mode; - char *safe_mode_exec_dir; - long enable_dl; + long safe_mode; + long sql_safe_mode; + char *safe_mode_exec_dir; + long enable_dl; long memory_limit; @@ -47,11 +47,11 @@ struct _php_core_globals { char *doc_root; char *user_dir; char *include_path; - char *open_basedir; + char *open_basedir; char *extension_dir; char *upload_tmp_dir; - long upload_max_filesize; + long upload_max_filesize; char *auto_prepend_file; char *auto_append_file; @@ -63,8 +63,15 @@ struct _php_core_globals { long y2k_compliance; - unsigned char header_is_being_sent; + unsigned char header_is_being_sent; }; #endif /* _PHP_GLOBALS_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */