? wez.streams.php
? index.html
? config.nice.cgi
? Session.vim
? wez.streams.2.diff
? wez.streams.diff.gz
Index: ext/bz2/bz2.c
===================================================================
RCS file: /repository/php4/ext/bz2/bz2.c,v
retrieving revision 1.34
diff -u -w -B -b -r1.34 bz2.c
--- ext/bz2/bz2.c 27 Jan 2002 17:24:31 -0000 1.34
+++ ext/bz2/bz2.c 18 Feb 2002 12:00:21 -0000
@@ -128,8 +128,21 @@
}
/* If it is a resource, than its a 'FILE *' resource */
else {
- ZEND_FETCH_RESOURCE(fp, FILE *, file, -1, "File Handle", php_file_le_fopen());
- bz = BZ2_bzdopen(fileno(fp), Z_STRVAL_PP(mode));
+ int type;
+ int fd;
+
+ fp = (FILE*) zend_fetch_resource(file TSRMLS_CC, -1, "File-Handle", &type, 2, php_file_le_fopen(), php_file_le_stream());
+ ZEND_VERIFY_RESOURCE(fp);
+#if HAVE_PHP_STREAM
+ if (type == php_file_le_stream()) {
+ if (!php_stream_cast((php_stream*)fp, PHP_STREAM_AS_FD, (void*)&fd, REPORT_ERRORS))
+ RETURN_FALSE;
+ }
+ else
+#endif
+ fd = fileno(fp);
+
+ bz = BZ2_bzdopen(fd, Z_STRVAL_PP(mode));
}
if (bz == NULL) {
Index: ext/curl/curl.c
===================================================================
RCS file: /repository/php4/ext/curl/curl.c,v
retrieving revision 1.105
diff -u -w -B -b -r1.105 curl.c
--- ext/curl/curl.c 27 Jan 2002 06:11:50 -0000 1.105
+++ ext/curl/curl.c 18 Feb 2002 12:00:26 -0000
@@ -699,7 +699,18 @@
case CURLOPT_WRITEHEADER:
case CURLOPT_STDERR: {
FILE *fp = NULL;
- ZEND_FETCH_RESOURCE(fp, FILE *, zvalue, -1, "File-Handle", php_file_le_fopen());
+ int type;
+ void * what;
+
+ what = zend_fetch_resource(zvalue TSRMLS_CC, -1, "File-Handle", &type, 2, php_file_le_fopen(), php_file_le_stream());
+ ZEND_VERIFY_RESOURCE(what);
+
+#if HAVE_PHP_STREAM
+ if (type == php_file_le_stream()) {
+ if (!php_stream_cast((php_stream*)what, PHP_STREAM_AS_STDIO, (void*)&fp, REPORT_ERRORS))
+ RETURN_FALSE;
+ }
+#endif
if (!fp) {
RETURN_FALSE;
}
Index: ext/mailparse/mailparse.c
===================================================================
RCS file: /repository/php4/ext/mailparse/mailparse.c,v
retrieving revision 1.17
diff -u -w -B -b -r1.17 mailparse.c
--- ext/mailparse/mailparse.c 4 Feb 2002 14:27:37 -0000 1.17
+++ ext/mailparse/mailparse.c 18 Feb 2002 12:00:38 -0000
@@ -183,6 +183,7 @@
zval * file, * item;
FILE *infp, *outfp=NULL, *partfp=NULL;
int type;
+ void * what;
char * buffer = NULL;
char * outpath = NULL;
int nparts = 0;
@@ -190,9 +191,20 @@
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "r", &file))
return;
- infp = (FILE*)zend_fetch_resource(&file TSRMLS_CC, -1, "File-Handle", &type, 1, php_file_le_fopen());
+ what = zend_fetch_resource(&file TSRMLS_CC, -1, "File-Handle", &type, 2, php_file_le_fopen(), php_file_le_stream());
ZEND_VERIFY_RESOURCE(infp);
+#if HAVE_PHP_STREAM
+ if (type == php_file_le_stream()) {
+ if (php_stream_cast((php_stream *) what, PHP_STREAM_AS_STDIO, (void *) &infp, 1) == FAILURE) {
+ RETURN_FALSE;
+ }
+ }
+ else
+#endif
+ infp = (FILE*)what;
+
+
outfp = php_open_temporary_file(NULL, "mailparse", &outpath TSRMLS_CC);
if (outfp == NULL) {
zend_error(E_WARNING, "%s(): unable to open temp file", get_active_function_name(TSRMLS_C));
@@ -401,6 +413,18 @@
/* {{{ proto boolean mailparse_stream_encode(resource sourcefp, resource destfp, string encoding)
Streams data from source file pointer, apply encoding and write to destfp */
+#if HAVE_PHP_STREAM
+static int mailparse_stream_output(int c, void * stream)
+{
+ char buf = c;
+ return php_stream_write((php_stream*)stream, &buf, 1);
+}
+static int mailparse_stream_flush(void * stream)
+{
+ return php_stream_flush((php_stream*)stream);
+}
+#endif
+
static int mailparse_fp_output(int c, void * fp)
{
return fputc(c, (FILE*)fp);
@@ -414,6 +438,11 @@
{
zval ** srcfile, ** destfile, ** encod;
FILE * srcfp, * destfp;
+ void * what;
+ int type;
+#if HAVE_PHP_STREAM
+ php_stream * srcstream, * deststream;
+#endif
char * buf;
size_t len;
size_t bufsize = 2048;
@@ -427,12 +456,32 @@
if (Z_TYPE_PP(srcfile) == IS_RESOURCE && Z_LVAL_PP(srcfile) == 0) {
RETURN_FALSE;
}
- ZEND_FETCH_RESOURCE(srcfp, FILE *, srcfile, -1, "File-Handle", php_file_le_fopen());
-
if (Z_TYPE_PP(destfile) == IS_RESOURCE && Z_LVAL_PP(destfile) == 0) {
RETURN_FALSE;
}
- ZEND_FETCH_RESOURCE(destfp, FILE *, destfile, -1, "File-Handle", php_file_le_fopen());
+
+ what = zend_fetch_resource(srcfile TSRMLS_CC, -1, "File-Handle", &type, 2, php_file_le_fopen(), php_file_le_stream());
+ ZEND_VERIFY_RESOURCE(what);
+
+#if HAVE_PHP_STREAM
+ if (type == php_file_le_stream()) {
+ srcstream = (php_stream*)what;
+ }
+ else
+#endif
+ srcfp = (FILE*)what;
+
+
+ what = zend_fetch_resource(destfile TSRMLS_CC, -1, "File-Handle", &type, 2, php_file_le_fopen(), php_file_le_stream());
+ ZEND_VERIFY_RESOURCE(what);
+#if HAVE_PHP_STREAM
+ if (type == php_file_le_stream()) {
+ deststream = (php_stream*)what;
+ }
+ else
+#endif
+ destfp = (FILE*)what;
+
convert_to_string_ex(encod);
enc = mbfl_name2no_encoding(Z_STRVAL_PP(encod));
@@ -447,6 +496,28 @@
buf = emalloc(bufsize);
RETVAL_TRUE;
+#if HAVE_PHP_STREAM
+ if (type == php_file_le_stream()) {
+ conv = mbfl_convert_filter_new(mbfl_no_encoding_8bit,
+ enc,
+ mailparse_stream_output,
+ mailparse_stream_flush,
+ deststream
+ );
+
+ while(!php_stream_eof(srcstream)) {
+ len = php_stream_read(srcstream, buf, bufsize);
+ if (len > 0)
+ {
+ int i;
+ for (i=0; i here! */
}
Index: ext/recode/recode.c
===================================================================
RCS file: /repository/php4/ext/recode/recode.c,v
retrieving revision 1.20
diff -u -w -B -b -r1.20 recode.c
--- ext/recode/recode.c 11 Dec 2001 15:30:18 -0000 1.20
+++ ext/recode/recode.c 18 Feb 2002 12:00:53 -0000
@@ -26,6 +26,7 @@
#include "php.h"
#include "php_recode.h"
+#include "php_streams.h"
#if HAVE_LIBRECODE
#include "ext/standard/info.h"
@@ -171,18 +173,34 @@
}
in_fp = zend_fetch_resource(input TSRMLS_CC,-1, "File-Handle", &in_type,
- 2, php_file_le_fopen(), php_file_le_popen());
+ 3, php_file_le_fopen(), php_file_le_popen(), php_file_le_stream());
+
if (!in_fp) {
php_error(E_WARNING,"Unable to find input file identifier");
RETURN_FALSE;
}
+#if HAVE_PHP_STREAM
+ if (in_type == php_file_le_stream()) {
+ if (!php_stream_cast((php_stream*)in_fp, PHP_STREAM_AS_STDIO, &in_fp, REPORT_ERRORS)) {
+ RETURN_FALSE;
+ }
+ }
+#endif
+
out_fp = zend_fetch_resource(output TSRMLS_CC,-1, "File-Handle", &out_type,
- 2, php_file_le_fopen(), php_file_le_popen());
+ 3, php_file_le_fopen(), php_file_le_popen(), php_file_le_stream());
if (!out_fp) {
php_error(E_WARNING,"Unable to find output file identifier");
RETURN_FALSE;
}
+#if HAVE_PHP_STREAM
+ if (out_type == php_file_le_stream()) {
+ if (!php_stream_cast((php_stream*)out_fp, PHP_STREAM_AS_STDIO, &out_fp, REPORT_ERRORS)) {
+ RETURN_FALSE;
+ }
+ }
+#endif
convert_to_string_ex(req);
Index: ext/standard/basic_functions.c
===================================================================
RCS file: /repository/php4/ext/standard/basic_functions.c,v
retrieving revision 1.442
diff -u -w -B -b -r1.442 basic_functions.c
--- ext/standard/basic_functions.c 10 Feb 2002 17:38:15 -0000 1.442
+++ ext/standard/basic_functions.c 18 Feb 2002 12:00:54 -0000
@@ -20,6 +20,7 @@
/* $Id: basic_functions.c,v 1.442 2002/02/10 17:38:15 jason Exp $ */
#include "php.h"
+#include "php_streams.h"
#include "php_main.h"
#include "php_globals.h"
#include "php_ini.h"
@@ -274,6 +275,7 @@
PHP_FE(wordwrap, NULL)
PHP_FE(htmlspecialchars, NULL)
PHP_FE(htmlentities, NULL)
+ PHP_FE(html_entity_decode, NULL)
PHP_FE(get_html_translation_table, NULL)
PHP_NAMED_FE(md5,php_if_md5, NULL)
PHP_NAMED_FE(md5_file,php_if_md5_file, NULL)
@@ -990,6 +992,16 @@
if (PG(allow_url_fopen)) {
+
+#if HAVE_PHP_STREAM
+ if (FAILURE == php_register_url_stream_wrapper("http", php_stream_url_wrap_http TSRMLS_CC))
+ return FAILURE;
+# if HAVE_OPENSSL_EXT
+ if (FAILURE == php_register_url_stream_wrapper("https", php_stream_url_wrap_http TSRMLS_CC))
+ return FAILURE;
+# endif
+#endif
+
if (FAILURE == php_register_url_wrapper("http", php_fopen_url_wrap_http TSRMLS_CC)) {
return FAILURE;
}
Index: ext/standard/file.c
===================================================================
RCS file: /repository/php4/ext/standard/file.c,v
retrieving revision 1.204
diff -u -w -B -b -r1.204 file.c
--- ext/standard/file.c 11 Jan 2002 10:44:24 -0000 1.204
+++ ext/standard/file.c 18 Feb 2002 12:00:55 -0000
@@ -17,7 +17,7 @@
| Andi Gutmans |
| Zeev Suraski |
| PHP 4.0 patches by Thies C. Arntzen (thies@thieso.net) |
- | PHP 4.1 streams by Wez Furlong (wez@thebrainroom.com) |
+ | PHP streams by Wez Furlong (wez@thebrainroom.com) |
+----------------------------------------------------------------------+
*/
@@ -72,6 +72,7 @@
#endif
#include "fsock.h"
#include "fopen_wrappers.h"
+#include "php_streams.h"
#include "php_globals.h"
#ifdef HAVE_SYS_FILE_H
@@ -135,8 +136,8 @@
static void _file_stream_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
php_stream *stream = (php_stream*)rsrc->ptr;
-
- php_stream_close(stream);
+ /* the stream might be a pipe, so set the return value for pclose */
+ FG(pclose_ret) = php_stream_close(stream);
}
#endif
@@ -568,6 +569,17 @@
php_error(E_WARNING, "tmpfile(): %s", strerror(errno));
RETURN_FALSE;
}
+#if HAVE_PHP_STREAM
+ {
+ php_stream * stream = php_stream_fopen_from_file(fp, "r+");
+ if (stream == NULL) {
+ zend_error(E_WARNING, "tmpfile(): %s", strerror(errno));
+ RETURN_FALSE;
+ }
+ ZEND_REGISTER_RESOURCE(return_value, stream, le_stream);
+ return;
+ }
+#endif
ZEND_REGISTER_RESOURCE(return_value, fp, le_fopen);
}
/* }}} */
@@ -586,7 +598,7 @@
convert_to_string_ex(zfilename);
convert_to_string_ex(zmode);
- stream = php_stream_fopen(Z_STRVAL_PP(zfilename), Z_STRVAL_PP(zmode));
+ stream = php_stream_fopen(Z_STRVAL_PP(zfilename), Z_STRVAL_PP(zmode), NULL TSRMLS_C);
if (stream == NULL) {
zend_error(E_WARNING, "%s(): unable to open %s: %s", get_active_function_name(TSRMLS_C), Z_STRVAL_PP(zfilename), strerror(errno));
@@ -607,6 +619,9 @@
int *sock;
int use_include_path = 0;
int issock=0, socketd=0;
+#if HAVE_PHP_STREAM
+ php_stream * stream;
+#endif
switch(ZEND_NUM_ARGS()) {
case 2:
@@ -626,6 +641,19 @@
}
convert_to_string_ex(arg1);
convert_to_string_ex(arg2);
+
+#if HAVE_PHP_STREAM
+ stream = php_stream_open_wrapper(Z_STRVAL_PP(arg1), Z_STRVAL_PP(arg2),
+ use_include_path | ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ NULL TSRMLS_CC);
+ if (stream == NULL) {
+ RETURN_FALSE;
+ }
+ FG(fgetss_state) = 0;
+ ZEND_REGISTER_RESOURCE(return_value, stream, le_stream);
+ return;
+#endif
+
p = estrndup(Z_STRVAL_PP(arg2), Z_STRLEN_PP(arg2));
/*
@@ -742,12 +770,13 @@
{
zval **arg1;
void *what;
+ int type;
if (ARG_COUNT(ht) != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
WRONG_PARAM_COUNT;
}
- what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", NULL, 1, le_popen);
+ what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 2, le_popen, le_stream);
ZEND_VERIFY_RESOURCE(what);
zend_list_delete(Z_LVAL_PP(arg1));
@@ -850,7 +879,19 @@
}
#if HAVE_PHP_STREAM
else if (type == le_stream) {
- if (php_stream_cast((php_stream *) what, PHP_STREAM_AS_SOCKETD, (void *) &socketd, 1) == FAILURE) {
+ if (php_stream_is((php_stream*)what, PHP_STREAM_IS_SOCKET)) {
+ /* TODO: check if the blocking mode is changed elsewhere, and see if we
+ * can integrate these calls into php_stream_sock_set_blocking */
+ php_stream_cast((php_stream *) what, PHP_STREAM_AS_SOCKETD, (void *) &socketd, REPORT_ERRORS);
+
+ if (php_set_sock_blocking(socketd, block) == FAILURE)
+ RETURN_FALSE;
+
+ php_stream_sock_set_blocking((php_stream*)what, block == 0 ? 0 : 1);
+ RETURN_TRUE;
+ }
+
+ if (php_stream_cast((php_stream *) what, PHP_STREAM_AS_SOCKETD, (void *) &socketd, REPORT_ERRORS) == FAILURE) {
RETURN_FALSE;
}
}
@@ -889,10 +930,9 @@
zend_get_parameters_ex(ZEND_NUM_ARGS(), &socket, &seconds, µseconds)==FAILURE) {
WRONG_PARAM_COUNT;
}
- /* XXX: add stream support --Wez. */
- what = zend_fetch_resource(socket TSRMLS_CC, -1, "File-Handle", &type, 1, le_socket);
+
+ what = zend_fetch_resource(socket TSRMLS_CC, -1, "File-Handle", &type, 2, le_socket, le_stream);
ZEND_VERIFY_RESOURCE(what);
- socketd = *(int *) what;
convert_to_long_ex(seconds);
t.tv_sec = Z_LVAL_PP(seconds);
@@ -905,6 +945,23 @@
else
t.tv_usec = 0;
+ if (type == le_socket) {
+ socketd = *(int *) what;
+ }
+#if HAVE_PHP_STREAM
+ else if (type == le_stream) {
+ if (php_stream_is((php_stream*)what, PHP_STREAM_IS_SOCKET)) {
+ php_stream_sock_set_timeout((php_stream*)what, &t);
+ RETURN_TRUE;
+ }
+
+ if (php_stream_cast((php_stream *) what, PHP_STREAM_AS_SOCKETD, (void *) &socketd, 1) == FAILURE) {
+ RETURN_FALSE;
+ }
+ }
+#endif
+
+
php_sockset_timeout(socketd, &t);
RETURN_TRUE;
#endif /* HAVE_SYS_TIME_H */
@@ -926,11 +983,24 @@
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &socket) == FAILURE) {
WRONG_PARAM_COUNT;
}
- /* XXX: add stream support --Wez. */
- what = zend_fetch_resource(socket TSRMLS_CC, -1, "File-Handle", &type, 1, le_socket);
+ what = zend_fetch_resource(socket TSRMLS_CC, -1, "File-Handle", &type, 2, le_socket, le_stream);
ZEND_VERIFY_RESOURCE(what);
+ if (type == le_socket) {
socketd = *(int *) what;
+ }
+#if HAVE_PHP_STREAM
+ else if (type == le_stream) {
+ if (php_stream_is((php_stream*)what, PHP_STREAM_IS_SOCKET)) {
+ /* TODO: implement */
+ RETURN_FALSE;
+ }
+ if (php_stream_cast((php_stream *) what, PHP_STREAM_AS_SOCKETD, (void *) &socketd, 1) == FAILURE) {
+ RETURN_FALSE;
+ }
+ }
+#endif
+
sock = php_get_socket(socketd);
array_init(return_value);
@@ -1356,11 +1426,13 @@
break;
}
- /* XXX: add stream support --Wez. */
-
- what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 2, le_fopen, le_popen);
+ what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 3, le_fopen, le_popen, le_stream);
ZEND_VERIFY_RESOURCE(what);
-
+#if HAVE_PHP_STREAM
+ if (type == le_stream && !php_stream_is((php_stream*)what, PHP_STREAM_IS_STDIO)) {
+ RETURN_FALSE;
+ }
+#endif
convert_to_long_ex(arg2);
buff = Z_LVAL_PP(arg2);
@@ -1381,15 +1453,24 @@
{
zval **arg1;
void *what;
+ int type;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
WRONG_PARAM_COUNT;
}
- /* XXX: add stream support --Wez. */
- what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", NULL, 2, le_fopen, le_popen);
+ what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 3, le_fopen, le_popen, le_stream);
ZEND_VERIFY_RESOURCE(what);
+#if HAVE_PHP_STREAM
+ if (type == le_stream) {
+ if (-1 == php_stream_rewind((php_stream*)what)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+ }
+#endif
+
rewind((FILE *) what);
RETURN_TRUE;
}
@@ -1402,15 +1483,25 @@
zval **arg1;
void *what;
long ret;
+ int type;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
WRONG_PARAM_COUNT;
}
- /* XXX: add stream support --Wez. */
- what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", NULL, 2, le_fopen, le_popen);
+ what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 2, le_fopen, le_popen, le_stream);
ZEND_VERIFY_RESOURCE(what);
+#if HAVE_PHP_STREAM
+ if (type == le_stream) {
+ ret = php_stream_tell((php_stream*)what);
+ if (ret == -1) {
+ RETURN_FALSE;
+ }
+ RETURN_LONG(ret);
+ }
+#endif
+
ret = ftell((FILE *) what);
if (ret == -1) {
RETURN_FALSE;
@@ -1427,14 +1518,14 @@
zval **arg1, **arg2, **arg3;
int argcount = ZEND_NUM_ARGS(), whence = SEEK_SET;
void *what;
+ int type;
if (argcount < 2 || argcount > 3 ||
zend_get_parameters_ex(argcount, &arg1, &arg2, &arg3) == FAILURE) {
WRONG_PARAM_COUNT;
}
- /* XXX: add stream support --Wez. */
- what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", NULL, 2, le_fopen, le_popen);
+ what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 3, le_fopen, le_popen, le_stream);
ZEND_VERIFY_RESOURCE(what);
convert_to_long_ex(arg2);
@@ -1443,6 +1534,13 @@
whence = Z_LVAL_PP(arg3);
}
+#if HAVE_PHP_STREAM
+ if (type == le_stream) {
+ RETURN_LONG(php_stream_seek((php_stream*)what, Z_LVAL_PP(arg2), whence));
+ }
+#endif
+
+
RETURN_LONG(fseek((FILE *) what, Z_LVAL_PP(arg2), whence));
}
@@ -1508,13 +1606,59 @@
}
/* }}} */
+#if HAVE_PHP_STREAM
+static size_t php_passthru_stream(php_stream * stream TSRMLS_DC)
+{
+ size_t bcount = 0;
+ int ready = 0;
+ char buf[8192];
+ int fd;
+
+#ifdef HAVE_MMAP
+ if (!php_stream_is(stream, PHP_STREAM_IS_SOCKET)
+ && php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&fd, 0))
+ {
+ struct stat sbuf;
+ off_t off;
+ void *p;
+ size_t len;
+
+ fstat(fd, &sbuf);
+
+ if (sbuf.st_size > sizeof(buf)) {
+ off = php_stream_tell(stream);
+ len = sbuf.st_size - off;
+ p = mmap(0, len, PROT_READ, MAP_SHARED, fd, off);
+ if (p != (void *) MAP_FAILED) {
+ BG(mmap_file) = p;
+ BG(mmap_len) = len;
+ PHPWRITE(p, len);
+ BG(mmap_file) = NULL;
+ munmap(p, len);
+ bcount += len;
+ ready = 1;
+ }
+ }
+ }
+#endif
+ if(!ready) {
+ int b;
+
+ while ((b = php_stream_read(stream, buf, sizeof(buf))) > 0) {
+ PHPWRITE(buf, b);
+ bcount += b;
+ }
+ }
+ return bcount;
+}
+#endif
+
/* {{{ php_passthru_fd */
static size_t php_passthru_fd(int socketd, FILE *fp, int issock TSRMLS_DC)
{
size_t bcount = 0;
int ready = 0;
char buf[8192];
- /* XXX: add stream support --Wez. */
#ifdef HAVE_MMAP
if (!issock) {
@@ -1567,6 +1711,9 @@
int use_include_path=0;
int issock=0, socketd=0;
int rsrc_id;
+#if HAVE_PHP_STREAM
+ php_stream * stream;
+#endif
/* check args */
switch (ZEND_NUM_ARGS()) {
@@ -1587,6 +1734,17 @@
}
convert_to_string_ex(arg1);
+#if HAVE_PHP_STREAM
+ stream = php_stream_open_wrapper(Z_STRVAL_PP(arg1), "rb",
+ use_include_path | ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ NULL TSRMLS_CC);
+ if (stream) {
+ size = php_passthru_stream(stream TSRMLS_CC);
+ php_stream_close(stream);
+ }
+ RETURN_LONG(size);
+#endif
+
/*
* We need a better way of returning error messages from
* php_fopen_wrapper().
@@ -1663,10 +1821,17 @@
WRONG_PARAM_COUNT;
}
- /* XXX: add stream support --Wez. */
- what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 3, le_fopen, le_popen, le_socket);
+ what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream);
ZEND_VERIFY_RESOURCE(what);
+#if HAVE_PHP_STREAM
+ if (type == le_stream) {
+ size = php_passthru_stream((php_stream*)what TSRMLS_CC);
+ RETURN_LONG(size);
+ }
+#endif
+
+
if (type == le_socket) {
issock = 1;
socketd = *(int *) what;
@@ -1760,17 +1925,32 @@
if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &fp, &size) == FAILURE) {
WRONG_PARAM_COUNT;
}
- /* XXX: add stream support --Wez. */
- what = zend_fetch_resource(fp TSRMLS_CC,-1, "File-Handle", &type, 3, le_fopen, le_popen, le_socket);
+ what = zend_fetch_resource(fp TSRMLS_CC,-1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream);
ZEND_VERIFY_RESOURCE(what);
- if (type == le_socket) {
+ convert_to_long_ex(size);
+
+#if HAVE_PHP_STREAM
+ if (type == le_stream) {
+ int fd;
+
+ if (php_stream_is((php_stream*)what, PHP_STREAM_IS_SOCKET)) {
php_error(E_WARNING, "can't truncate sockets!");
RETURN_FALSE;
}
+ if (php_stream_cast((php_stream*)what, PHP_STREAM_AS_FD, (void*)&fd, 1)) {
+ ret = ftruncate(fd, Z_LVAL_PP(size));
+ RETURN_LONG(ret + 1);
+ }
+ RETURN_FALSE;
+ }
+#endif
- convert_to_long_ex(size);
+ if (type == le_socket) {
+ php_error(E_WARNING, "can't truncate sockets!");
+ RETURN_FALSE;
+ }
ret = ftruncate(fileno((FILE *) what), Z_LVAL_PP(size));
RETURN_LONG(ret + 1);
@@ -1787,6 +1967,7 @@
int type;
void *what;
struct stat stat_sb;
+ int fd;
char *stat_sb_names[13]={"dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
"size", "atime", "mtime", "ctime", "blksize", "blocks"};
@@ -1794,12 +1975,25 @@
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &fp) == FAILURE) {
WRONG_PARAM_COUNT;
}
- /* XXX: add stream support --Wez. */
- what = zend_fetch_resource(fp TSRMLS_CC,-1, "File-Handle", &type, 3, le_fopen, le_popen, le_socket);
+ what = zend_fetch_resource(fp TSRMLS_CC,-1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream);
ZEND_VERIFY_RESOURCE(what);
- if (fstat(fileno((FILE *) what), &stat_sb)) {
+#if HAVE_PHP_STREAM
+ if (type == le_stream) {
+ if (!php_stream_cast((php_stream*)what, PHP_STREAM_AS_FD, (void*)&fd, 1)) {
+ RETURN_FALSE;
+ }
+ }
+ else
+#endif
+ if (type == le_socket) {
+ fd = *(int*)what;
+ }
+ else
+ fd = fileno((FILE*) what);
+
+ if (fstat(fd, &stat_sb)) {
RETURN_FALSE;
}
@@ -1971,16 +2165,10 @@
if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
WRONG_PARAM_COUNT;
}
- /* XXX: add stream support --Wez. */
- what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 3, le_fopen, le_popen, le_socket);
+ what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream);
ZEND_VERIFY_RESOURCE(what);
- if (type == le_socket) {
- issock = 1;
- socketd = *(int *) what;
- }
-
convert_to_long_ex(arg2);
len = Z_LVAL_PP(arg2);
if (len < 0) {
@@ -1988,9 +2176,22 @@
RETURN_FALSE;
}
+ if (type == le_socket) {
+ issock = 1;
+ socketd = *(int *) what;
+ }
+
Z_STRVAL_P(return_value) = emalloc(len + 1);
/* needed because recv doesnt put a null at the end*/
+ Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0;
+#if HAVE_PHP_STREAM
+ if (type == le_stream) {
+ php_stream * stream = (php_stream*)what;
+ Z_STRLEN_P(return_value) = php_stream_read(stream, Z_STRVAL_P(return_value), len);
+ }
+ else
+#endif
if (!issock) {
#ifdef HAVE_FLUSHIO
if (type == le_fopen) {
@@ -2001,7 +2202,6 @@
} else {
Z_STRLEN_P(return_value) = SOCK_FREAD(Z_STRVAL_P(return_value), len, socketd);
}
- Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0;
if (PG(magic_quotes_runtime)) {
Z_STRVAL_P(return_value) = php_addslashes(Z_STRVAL_P(return_value),
Z_STRLEN_P(return_value), &Z_STRLEN_P(return_value), 1 TSRMLS_CC);
@@ -2025,6 +2225,9 @@
int issock=0;
int socketd=0;
void *what;
+#if HAVE_PHP_STREAM
+ php_stream * stream;
+#endif
switch(ZEND_NUM_ARGS()) {
case 2:
@@ -2051,15 +2254,19 @@
/* NOTREACHED */
break;
}
- /* XXX: add stream support --Wez. */
- what = zend_fetch_resource(fd TSRMLS_CC,-1, "File-Handle", &type, 3, le_fopen, le_popen, le_socket);
+ what = zend_fetch_resource(fd TSRMLS_CC,-1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream);
ZEND_VERIFY_RESOURCE(what);
if (type == le_socket) {
issock = 1;
socketd = *(int *) what;
}
+#if HAVE_PHP_STREAM
+ if (type == le_stream) {
+ stream = (php_stream*)what;
+ }
+#endif
convert_to_long_ex(bytes);
len = Z_LVAL_PP(bytes);
@@ -2071,6 +2278,17 @@
buf = emalloc(len + 1);
/*needed because recv doesnt set null char at end*/
memset(buf, 0, len + 1);
+
+#if HAVE_PHP_STREAM
+ if (type == le_stream) {
+ if (php_stream_gets(stream, buf, len) == NULL) {
+ efree(buf);
+ RETURN_FALSE;
+ }
+ }
+ else
+#endif
+
if (FP_FGETS(buf, len, socketd, (FILE *) what, issock) == NULL) {
efree(buf);
RETURN_FALSE;
@@ -2132,6 +2350,19 @@
/* read a new line from input, as at start of routine */
memset(buf, 0, len+1);
+
+#if HAVE_PHP_STREAM
+ if (type == le_stream) {
+ if (php_stream_gets(stream, buf, len) == NULL) {
+ efree(lineEnd);
+ efree(temp);
+ efree(buf);
+ zval_ptr_dtor(&return_value);
+ RETURN_FALSE;
+ }
+ }
+ else
+#endif
if (FP_FGETS(buf, len, socketd, (FILE *) what, issock) == NULL) {
efree(lineEnd);
efree(temp);
@@ -2218,7 +2449,6 @@
ptr = *buf = emalloc(step);
max_len = step;
- /* XXX: add stream support --Wez. */
while((ret = FP_FREAD(ptr, max_len - len, socket, fp, issock))) {
len += ret;
Index: ext/standard/fsock.c
===================================================================
RCS file: /repository/php4/ext/standard/fsock.c,v
retrieving revision 1.84
diff -u -w -B -b -r1.84 fsock.c
--- ext/standard/fsock.c 11 Dec 2001 15:30:31 -0000 1.84
+++ ext/standard/fsock.c 18 Feb 2002 12:00:56 -0000
@@ -152,6 +152,139 @@
/* }}} */
/* {{{ php_fsockopen() */
+#if HAVE_PHP_STREAM
+static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
+{
+ char * host;
+ int host_len;
+ int port = -1;
+ zval * zerrno = NULL, * zerrstr = NULL;
+ double timeout = 60;
+ unsigned long conv;
+ struct timeval tv;
+ char * hashkey = NULL;
+ php_stream * stream = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|lzzd", &host, &host_len, &port, &zerrno, &zerrstr, &timeout) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ hashkey = emalloc(host_len + 10);
+ sprintf(hashkey, "%s:%d", host, port);
+
+#if 0
+ if (persistent && zend_hash_find(&FG(ht_fsock_keys), key, strlen(key) + 1,
+ (void *) &stream) == SUCCESS)
+ {
+ efree(key);
+ ZEND_REGISTER_RESOURCE(return_value, stream, php_file_le_stream());
+ return;
+ }
+#else
+ persistent = 0; /* don't allow them for the moment */
+#endif
+
+ /* prepare the timeout value for use */
+ conv = (unsigned long) (timeout * 1000000.0);
+ tv.tv_sec = conv / 1000000;
+ tv.tv_usec = conv % 1000000;
+
+ if (zerrno) {
+ zval_dtor(zerrno);
+ ZVAL_LONG(zerrno, 0);
+ }
+ if (zerrstr) {
+ zval_dtor(zerrstr);
+ ZVAL_STRING(zerrno, "", 1);
+ }
+
+ if (port != -1) { /* connect to a host */
+ enum php_sslflags_t { php_ssl_none, php_ssl_v23, php_ssl_tls };
+ enum php_sslflags_t ssl_flags;
+ struct {
+ char * proto;
+ int protolen;
+ int socktype;
+ enum php_sslflags_t ssl_flags;
+ /* more flags to be added here */
+ } sockmodes[] = {
+ { "udp://", 6, SOCK_DGRAM, php_ssl_none },
+ { "tcp://", 6, SOCK_STREAM, php_ssl_none },
+ { "ssl://", 6, SOCK_STREAM, php_ssl_v23 },
+ { "tls://", 6, SOCK_STREAM, php_ssl_tls },
+ /* more modes to be added here */
+ { NULL, 0, 0 }
+ };
+ int socktype = SOCK_STREAM;
+ int i;
+
+ for (i = 0; sockmodes[i].proto != NULL; i++) {
+ if (strncmp(host, sockmodes[i].proto, sockmodes[i].protolen) == 0) {
+ ssl_flags = sockmodes[i].ssl_flags;
+ socktype = sockmodes[i].socktype;
+ host += sockmodes[i].protolen;
+ break;
+ }
+ }
+#if !HAVE_OPENSSL_EXT
+ if (ssl_flags != php_ssl_none) {
+ zend_error(E_WARNING, "%s(): no SSL support in this build", get_active_function_name(TSRMLS_C));
+ }
+ else
+#endif
+ stream = php_stream_sock_open_host(host, port, socktype, timeout, persistent);
+
+#if HAVE_OPENSSL_EXT
+ if (stream) {
+ int ssl_ret = FAILURE;
+ switch(ssl_flags) {
+ case php_ssl_v23:
+ ssl_ret = php_stream_sock_ssl_activate_with_method(stream, 1, SSLv23_client_method());
+ break;
+ case php_ssl_tls:
+ ssl_ret = php_stream_sock_ssl_activate_with_method(stream, 1, TLSv1_client_method());
+ break;
+ default:
+ /* unknown ?? */
+ }
+ if (ssl_ret == FAILURE)
+ zend_error(E_WARNING, "failed to activate SSL mode %d", ssl_flags);
+ }
+#endif
+
+ } else
+ stream = php_stream_sock_open_unix(host, persistent, &tv);
+
+ if (stream && persistent) {
+#if 0
+ zend_hash_update(&FG(ht_fsock_keys), hashkey, strlen(hashkey) + 1,
+ &stream, sizeof(stream), NULL);
+#endif
+ }
+
+out:
+
+ efree(hashkey);
+
+ if (stream == NULL) {
+ if (zerrno) {
+ zval_dtor(zerrno);
+ ZVAL_LONG(zerrno, errno);
+ }
+ if (zerrstr) {
+ zval_dtor(zerrstr);
+ ZVAL_STRING(zerrno, strerror(errno), 1);
+ }
+
+ RETURN_FALSE;
+ }
+
+ ZEND_REGISTER_RESOURCE(return_value, stream, php_file_le_stream());
+}
+
+#endif
+
+
/*
This function takes an optional third argument which should be
passed by reference. The error code from the connect call is written
@@ -288,14 +421,22 @@
Open Internet or Unix domain socket connection */
PHP_FUNCTION(fsockopen)
{
+#if HAVE_PHP_STREAM
+ php_fsockopen_stream(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+#else
php_fsockopen(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+#endif
}
/* }}} */
/* {{{ proto int pfsockopen(string hostname, int port [, int errno [, string errstr [, float timeout]]])
Open persistent Internet or Unix domain socket connection */
PHP_FUNCTION(pfsockopen)
{
+#if HAVE_PHP_STREAM
+ php_fsockopen_stream(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+#else
php_fsockopen(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+#endif
}
/* }}} */
@@ -633,95 +774,6 @@
return ret;
}
-
-/* {{{ stream abstraction */
-#if HAVE_PHP_STREAM
-static size_t php_sockop_write(php_stream * stream, const char * buf, size_t count)
-{
- php_sockbuf * sock = (php_sockbuf*)stream->abstract;
- return send(sock->socket, buf, count, 0);
-}
-
-static size_t php_sockop_read(php_stream * stream, char * buf, size_t count)
-{
- php_sockbuf * sock = (php_sockbuf*)stream->abstract;
- size_t ret = 0;
-
- if (sock->is_blocked)
- php_sockread_total(sock, count);
- else
- php_sockread(sock);
-
- if(count < 0)
- return ret;
-
- ret = MIN(TOREAD(sock), count);
- if (ret) {
- memcpy(buf, READPTR(sock), ret);
- sock->readpos += ret;
- }
-
- return ret;
-}
-
-static int php_sockop_close(php_stream * stream)
-{
- php_sockbuf * sock = (php_sockbuf*)stream->abstract;
-
- SOCK_CLOSE(sock->socket);
- SOCK_DESTROY(sock);
-
- return 0;
-}
-
-static int php_sockop_flush(php_stream * stream)
-{
- php_sockbuf * sock = (php_sockbuf*)stream->abstract;
- return fsync(sock->socket);
-}
-
-static int php_sockop_cast(php_stream * stream, int castas, void ** ret)
-{
- php_sockbuf * sock = (php_sockbuf*)stream->abstract;
- TSRMLS_FETCH();
-
- switch(castas) {
- case PHP_STREAM_AS_STDIO:
- if (ret) {
- /* DANGER!: data buffered in stream->readbuf will be forgotten! */
- if (TOREAD(sock) > 0)
- zend_error(E_WARNING, "%s(): buffered data lost during conversion to FILE*!", get_active_function_name(TSRMLS_C));
- *ret = fdopen(sock->socket, stream->mode);
- if (*ret)
- return SUCCESS;
- return FAILURE;
- }
- return SUCCESS;
- case PHP_STREAM_AS_FD:
- case PHP_STREAM_AS_SOCKETD:
- if (ret)
- *ret = (void*)sock->socket;
- return SUCCESS;
- default:
- return FAILURE;
- }
-}
-
-static char * php_sockop_gets(php_stream * stream, char *buf, size_t size)
-{
- php_sockbuf * sock = (php_sockbuf*)stream->abstract;
- return php_sock_fgets_internal(buf, size, sock);
-}
-
-php_stream_ops php_stream_socket_ops = {
- php_sockop_write, php_sockop_read,
- php_sockop_close, php_sockop_flush,
- NULL, php_sockop_gets,
- php_sockop_cast,
- "socket"
-};
-#endif
-/* }}} */
/* {{{ php_sock_fread() */
Index: ext/standard/fsock.h
===================================================================
RCS file: /repository/php4/ext/standard/fsock.h,v
retrieving revision 1.40
diff -u -w -B -b -r1.40 fsock.h
--- ext/standard/fsock.h 11 Dec 2001 15:30:31 -0000 1.40
+++ ext/standard/fsock.h 18 Feb 2002 12:00:56 -0000
@@ -31,11 +31,6 @@
#include "php_network.h"
-#if HAVE_PHP_STREAM
-extern php_stream_ops php_stream_socket_ops;
-#endif
-
-/* stream->abstract points to an instance of this */
struct php_sockbuf {
int socket;
unsigned char *readbuf;
@@ -50,9 +45,6 @@
size_t chunk_size;
struct timeval timeout;
char timeout_event;
-#if HAVE_PHP_STREAM
- php_stream * stream;
-#endif
};
typedef struct php_sockbuf php_sockbuf;
Index: ext/standard/html.c
===================================================================
RCS file: /repository/php4/ext/standard/html.c,v
retrieving revision 1.39
diff -u -w -B -b -r1.39 html.c
--- ext/standard/html.c 11 Dec 2001 15:30:31 -0000 1.39
+++ ext/standard/html.c 18 Feb 2002 12:00:56 -0000
@@ -23,7 +23,7 @@
#include "php.h"
#include "reg.h"
#include "html.h"
-
+#include "php_string.h"
#if HAVE_LOCALE_H
#include
#endif
@@ -123,6 +123,21 @@
{ NULL }
};
+static const struct {
+ unsigned short charcode;
+ char * entity;
+ int entitylen;
+ int flags;
+} basic_entities[] = {
+ { '&', "&", 5, 0 },
+ { '"', """, 6, ENT_HTML_QUOTE_DOUBLE },
+ { '\'', "'", 6, ENT_HTML_QUOTE_SINGLE },
+ { '<', "<", 4, 0 },
+ { '>', ">", 4, 0 },
+ { 0, NULL, 0, 0 }
+};
+
+
/* {{{ get_next_char
*/
inline static unsigned short get_next_char(enum entity_charset charset,
@@ -385,19 +400,88 @@
}
/* }}} */
+/* {{{ php_unescape_html_entities
+ */
+PHPAPI char *php_unescape_html_entities(unsigned char *old, int oldlen, int *newlen, int all, int quote_style, char *hint_charset)
+{
+ int i, maxlen, len, retlen;
+ int j, k;
+ char *replaced, *ret;
+ enum entity_charset charset = determine_charset(hint_charset);
+ int matches_map;
+ unsigned char replacement[15];
+
+ ret = estrdup(old);
+ retlen = oldlen;
+
+ if (all) {
+ /* look for a match in the maps for this charset */
+ for (j=0; entity_map[j].charset != cs_terminator; j++) {
+ if (entity_map[j].charset != charset)
+ continue;
+
+ for (k = entity_map[j].basechar; k <= entity_map[j].endchar; k++) {
+ unsigned char entity[32];
+ int entity_length = 0;
+
+ if (entity_map[j].table[k - entity_map[j].basechar] == NULL)
+ continue;
+
+
+ entity[0] = '&';
+ entity_length = strlen(entity_map[j].table[k - entity_map[j].basechar]);
+ strncpy(&entity[1], entity_map[j].table[k - entity_map[j].basechar], sizeof(entity) - 2);
+ entity[entity_length+1] = ';';
+ entity[entity_length+2] = '\0';
+ entity_length += 2;
+
+ /* When we have MBCS entities in the tables above, this will need to handle it */
+ if (k > 0xff)
+ zend_error(E_WARNING, "cannot yet handle MBCS in html_entity_decode()!");
+ replacement[0] = k;
+ replacement[1] = '\0';
+
+ replaced = php_str_to_str(ret, retlen, entity, entity_length, replacement, 1, &retlen);
+ efree(ret);
+ ret = replaced;
+ }
+ }
+ }
+
+ for (j = 0; basic_entities[j].charcode != 0; j++) {
+
+ if (basic_entities[j].flags && (quote_style & basic_entities[j].flags) == 0)
+ continue;
+
+ replacement[0] = basic_entities[j].charcode;
+ replacement[1] = '\0';
+
+ replaced = php_str_to_str(ret, retlen, basic_entities[j].entity, basic_entities[j].entitylen, replacement, 1, &retlen);
+ efree(ret);
+ ret = replaced;
+ }
+
+ *newlen = retlen;
+ return ret;
+}
+/* }}} */
+
+
+
+
/* {{{ php_escape_html_entities
*/
PHPAPI char *php_escape_html_entities(unsigned char *old, int oldlen, int *newlen, int all, int quote_style, char *hint_charset)
{
- int i, maxlen, len;
- char *new;
+ int i, j, maxlen, len;
+ char *replaced;
enum entity_charset charset = determine_charset(hint_charset);
int matches_map;
maxlen = 2 * oldlen;
if (maxlen < 128)
maxlen = 128;
- new = emalloc (maxlen);
+ replaced = emalloc (maxlen);
len = 0;
i = 0;
@@ -409,11 +493,10 @@
matches_map = 0;
if (len + 9 > maxlen)
- new = erealloc (new, maxlen += 128);
+ replaced = erealloc (replaced, maxlen += 128);
if (all) {
/* look for a match in the maps for this charset */
- int j;
unsigned char * rep;
@@ -435,41 +518,42 @@
}
if (matches_map) {
- new[len++] = '&';
- strcpy(new + len, rep);
+ replaced[len++] = '&';
+ strcpy(replaced + len, rep);
len += strlen(rep);
- new[len++] = ';';
+ replaced[len++] = ';';
}
}
if (!matches_map) {
- if (38 == this_char) {
- memcpy (new + len, "&", 5);
- len += 5;
- } else if (34 == this_char && !(quote_style&ENT_NOQUOTES)) {
- memcpy (new + len, """, 6);
- len += 6;
- } else if (39 == this_char && (quote_style&ENT_QUOTES)) {
- memcpy (new + len, "'", 6);
- len += 6;
- } else if (60 == this_char) {
- memcpy (new + len, "<", 4);
- len += 4;
- } else if (62 == this_char) {
- memcpy (new + len, ">", 4);
- len += 4;
- } else if (this_char > 0xff) {
+ int is_basic = 0;
+
+ for (j = 0; basic_entities[j].charcode != 0; j++) {
+ if ((basic_entities[j].charcode != this_char) ||
+ (basic_entities[j].flags && (quote_style & basic_entities[j].flags) == 0))
+ continue;
+
+ memcpy(replaced + len, basic_entities[j].entity, basic_entities[j].entitylen);
+ len += basic_entities[j].entitylen;
+
+ is_basic = 1;
+ break;
+
+ }
+ if (!is_basic) {
+ if (this_char > 0xff) {
/* a wide char without a named entity; pass through the original sequence */
- memcpy(new + len, mbsequence, mbseqlen);
+ memcpy(replaced + len, mbsequence, mbseqlen);
len += mbseqlen;
- } else {
- new [len++] = (unsigned char)this_char;
+
+ } else
+ replaced [len++] = (unsigned char)this_char;
}
}
}
- new [len] = '\0';
+ replaced [len] = '\0';
*newlen = len;
- return new;
+ return replaced;
}
@@ -481,15 +565,15 @@
{
char *str, *hint_charset = NULL;
int str_len, hint_charset_len, len, quote_style = ENT_COMPAT;
- char *new;
+ char *replaced;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls", &str, &str_len,
"e_style, &hint_charset, &hint_charset_len) == FAILURE) {
return;
}
- new = php_escape_html_entities(str, str_len, &len, all, quote_style, hint_charset);
- RETVAL_STRINGL(new, len, 0);
+ replaced = php_escape_html_entities(str, str_len, &len, all, quote_style, hint_charset);
+ RETVAL_STRINGL(replaced, len, 0);
}
/* }}} */
@@ -516,6 +600,25 @@
}
/* }}} */
+/* {{{ proto string html_entity_decode(string string [, int quote_style][, string charset])
+ Convert all applicable characters to HTML entities */
+PHP_FUNCTION(html_entity_decode)
+{
+ char *str, *hint_charset = NULL;
+ int str_len, hint_charset_len, len, quote_style = ENT_COMPAT;
+ char *replaced;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls", &str, &str_len,
+ "e_style, &hint_charset, &hint_charset_len) == FAILURE) {
+ return;
+ }
+
+ replaced = php_unescape_html_entities(str, str_len, &len, 1, quote_style, hint_charset);
+ RETVAL_STRINGL(replaced, len, 0);
+}
+/* }}} */
+
+
/* {{{ proto string htmlentities(string string [, int quote_style][, string charset])
Convert all applicable characters to HTML entities */
PHP_FUNCTION(htmlentities)
@@ -562,15 +665,14 @@
/* break thru */
case HTML_SPECIALCHARS:
- ind[0]=38; add_assoc_string(return_value, ind, "&", 1);
- if(quote_style&ENT_QUOTES) {
- ind[0]=39; add_assoc_string(return_value, ind, "'", 1);
- }
- if(!(quote_style&ENT_NOQUOTES)) {
- ind[0]=34; add_assoc_string(return_value, ind, """, 1);
+ for (j = 0; basic_entities[j].charcode != 0; j++) {
+
+ if (basic_entities[j].flags && (quote_style & basic_entities[j].flags) == 0)
+ continue;
+
+ ind[0] = basic_entities[j].charcode;
+ add_assoc_string(return_value, ind, basic_entities[j].entity, 1);
}
- ind[0]=60; add_assoc_string(return_value, ind, "<", 1);
- ind[0]=62; add_assoc_string(return_value, ind, ">", 1);
break;
}
}
Index: ext/standard/html.h
===================================================================
RCS file: /repository/php4/ext/standard/html.h,v
retrieving revision 1.11
diff -u -w -B -b -r1.11 html.h
--- ext/standard/html.h 11 Dec 2001 15:30:31 -0000 1.11
+++ ext/standard/html.h 18 Feb 2002 12:00:56 -0000
@@ -21,14 +21,19 @@
#ifndef HTML_H
#define HTML_H
-#define ENT_COMPAT 1
-#define ENT_QUOTES 2
-#define ENT_NOQUOTES 4
+#define ENT_HTML_QUOTE_NONE 0
+#define ENT_HTML_QUOTE_SINGLE 1
+#define ENT_HTML_QUOTE_DOUBLE 2
+
+#define ENT_COMPAT ENT_HTML_QUOTE_DOUBLE
+#define ENT_QUOTES (ENT_HTML_QUOTE_DOUBLE | ENT_HTML_QUOTE_SINGLE)
+#define ENT_NOQUOTES ENT_HTML_QUOTE_NONE
void register_html_constants(INIT_FUNC_ARGS);
PHP_FUNCTION(htmlspecialchars);
PHP_FUNCTION(htmlentities);
+PHP_FUNCTION(html_entity_decode);
PHP_FUNCTION(get_html_translation_table);
PHPAPI char *php_escape_html_entities(unsigned char *old, int oldlen, int *newlen, int all, int quote_style, char * hint_charset);
Index: ext/standard/http_fopen_wrapper.c
===================================================================
RCS file: /repository/php4/ext/standard/http_fopen_wrapper.c,v
retrieving revision 1.22
diff -u -w -B -b -r1.22 http_fopen_wrapper.c
--- ext/standard/http_fopen_wrapper.c 23 Dec 2001 00:46:13 -0000 1.22
+++ ext/standard/http_fopen_wrapper.c 18 Feb 2002 12:00:57 -0000
@@ -15,12 +15,14 @@
| Authors: Rasmus Lerdorf |
| Jim Winstead |
| Hartmut Holzgraefe |
+ | Wez Furlong |
+----------------------------------------------------------------------+
*/
/* $Id: http_fopen_wrapper.c,v 1.22 2001/12/23 00:46:13 alexwaugh Exp $ */
#include "php.h"
#include "php_globals.h"
+#include "php_streams.h"
#include "php_network.h"
#include
@@ -66,7 +68,243 @@
#include "php_fopen_wrappers.h"
-#define HTTP_HEADER_BLOCK_SIZE 128
+#define HTTP_HEADER_BLOCK_SIZE 1024
+
+#if HAVE_PHP_STREAM
+
+php_stream * php_stream_url_wrap_http(char * path, char * mode, int options, char ** opened_path TSRMLS_DC)
+{
+ php_stream * stream = NULL;
+ php_url * resource = NULL;
+ int use_ssl;
+ char * scratch = NULL;
+ char * tmp = NULL;
+ int scratch_len = 0;
+ int body = 0;
+ char location[HTTP_HEADER_BLOCK_SIZE];
+ zval * response_header = NULL;
+ int reqok = 0;
+ char * http_header_line = NULL;
+
+ resource = php_url_parse(path);
+ if (resource == NULL)
+ return NULL;
+
+ use_ssl = resource->scheme && resource->scheme[4] == 's';
+
+ /* choose default ports */
+ if (use_ssl && resource->port == 0)
+ resource->port = 443;
+ else if (resource->port == 0)
+ resource->port = 80;
+
+ stream = php_stream_sock_open_host(resource->host, resource->port, SOCK_STREAM, 0, 0);
+ if (stream == NULL)
+ goto out;
+
+#if HAVE_OPENSSL_EXT
+ if (use_ssl) {
+ if (php_stream_sock_ssl_activate(stream, 1) == FAILURE) {
+ if (options & REPORT_ERRORS) {
+ zend_error(E_WARNING, "Unable to activate SSL mode");
+ }
+ php_stream_close(stream);
+ stream = NULL;
+ goto out;
+ }
+ }
+#endif
+
+ scratch_len = strlen(path) + 32;
+ scratch = emalloc(scratch_len);
+
+ strcpy(scratch, "GET ");
+
+ /* file */
+ if (resource->path && *resource->path)
+ strlcat(scratch, resource->path, scratch_len);
+ else
+ strlcat(scratch, "/", scratch_len);
+
+ /* query string */
+ if (resource->query) {
+ strlcat(scratch, "?", scratch_len);
+ strlcat(scratch, resource->query, scratch_len);
+ }
+
+ /* protocol version we are speaking */
+ strlcat(scratch, " HTTP/1.0\r\n", scratch_len);
+
+ /* send it */
+ php_stream_write(stream, scratch, strlen(scratch));
+
+ /* authz header if it was specified */
+ if (resource->user && resource->pass) {
+ /* scratch is large enough, since it was made large enough for the whole URL */
+ strcpy(scratch, resource->user);
+ strcat(scratch, ":");
+ strcat(scratch, resource->pass);
+
+ tmp = php_base64_encode((unsigned char*)scratch, strlen(scratch), NULL);
+
+ if (snprintf(scratch, scratch_len, "Authorization: Basic %s\r\n", tmp) > 0)
+ php_stream_write(stream, scratch, strlen(scratch));
+
+ efree(tmp);
+ tmp = NULL;
+ }
+
+ /* if the user has configured who they are, send a From: line */
+ if (cfg_get_string("from", &tmp) == SUCCESS) {
+ if (snprintf(scratch, scratch_len, "From: %s\r\n", tmp) > 0)
+ php_stream_write(stream, scratch, strlen(scratch));
+ }
+
+ /* Send Host: header so name-based virtual hosts work */
+ if ((use_ssl && resource->port != 443) || (!use_ssl && resource->port != 80)) {
+ if (snprintf(scratch, scratch_len, "Host: %s:%i\r\n", resource->host, resource->port) > 0)
+ php_stream_write(stream, scratch, strlen(scratch));
+ }
+ else if (snprintf(scratch, scratch_len, "Host: %s\r\n", resource->host) > 0)
+ php_stream_write(stream, scratch, strlen(scratch));
+
+ php_stream_write_string(stream, "User-Agent: PHP/" PHP_VERSION "\r\n\r\n");
+
+ location[0] = '\0';
+
+ MAKE_STD_ZVAL(response_header);
+ array_init(response_header);
+
+ if (!php_stream_eof(stream)) {
+ /* get response header */
+ char tmp_line[128];
+
+ if (php_stream_gets(stream, tmp_line, sizeof(tmp_line)-1) != NULL) {
+ zval * http_response;
+
+ MAKE_STD_ZVAL(http_response);
+ if (strncmp(tmp_line + 8, " 200 ", 5) == 0)
+ reqok = 1;
+ Z_STRLEN_P(http_response) = strlen(tmp_line);
+ Z_STRVAL_P(http_response) = estrndup(tmp_line, Z_STRLEN_P(http_response));
+ if (Z_STRVAL_P(http_response)[Z_STRLEN_P(http_response)-1]=='\n') {
+ Z_STRVAL_P(http_response)[Z_STRLEN_P(http_response)-1]=0;
+ Z_STRLEN_P(http_response)--;
+ if (Z_STRVAL_P(http_response)[Z_STRLEN_P(http_response)-1]=='\r') {
+ Z_STRVAL_P(http_response)[Z_STRLEN_P(http_response)-1]=0;
+ Z_STRLEN_P(http_response)--;
+ }
+ }
+ Z_TYPE_P(http_response) = IS_STRING;
+ zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_response, sizeof(zval *), NULL);
+ }
+ }
+
+ /* read past HTTP headers */
+
+ http_header_line = emalloc(HTTP_HEADER_BLOCK_SIZE);
+
+ while (!body && !php_stream_eof(stream)) {
+
+ if (php_stream_gets(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE-1) != NULL) {
+ char * p;
+ int found_eol = 0;
+ int http_header_line_length;
+
+ http_header_line[HTTP_HEADER_BLOCK_SIZE-1] = '\0';
+ p = http_header_line;
+ while(*p) {
+ while(*p == '\n' || *p == '\r') {
+ *p = '\0';
+ p--;
+ found_eol = 1;
+ }
+ if (found_eol)
+ break;
+ p++;
+ }
+ http_header_line_length = p-http_header_line+1;
+
+ if (!strncasecmp(http_header_line, "Location: ", 10))
+ strlcpy(location, http_header_line + 10, sizeof(location));
+
+ if (http_header_line[0] == '\0')
+ body = 1;
+ else {
+ zval * http_header;
+
+ MAKE_STD_ZVAL(http_header);
+
+ ZVAL_STRINGL(http_header, http_header_line, http_header_line_length, 1);
+
+ zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_header, sizeof(zval *), NULL);
+ }
+ }
+ else
+ break;
+ }
+
+ if (!reqok) {
+ php_stream_close(stream);
+ stream = NULL;
+
+ if (location[0] != '\0') {
+
+ zval **response_header_new, *entry, **entryp;
+ char new_path[HTTP_HEADER_BLOCK_SIZE];
+
+ *new_path='\0';
+ if (strlen(location)<8 || (strncasecmp(location, "http://", 7) && strncasecmp(location, "https://", 8))) {
+ strcpy(new_path, resource->scheme);
+ strlcat(new_path, resource->host, sizeof(new_path));
+ if ((use_ssl && resource->port != 443) || (!use_ssl && resource->port != 80)) {
+ snprintf(new_path+strlen(new_path), sizeof(new_path)-strlen(new_path)-1, ":%d", resource->port);
+ }
+ if (*location != '/') {
+ php_dirname(resource->path, strlen(resource->path));
+ snprintf (new_path+strlen(new_path), sizeof(new_path)-strlen(new_path)-1, "%s/", resource->path);
+ }
+ strlcat(new_path, location, sizeof(new_path));
+ }
+ else {
+ strlcpy(new_path, location, sizeof(new_path));
+ }
+ stream = php_stream_url_wrap_http(new_path, mode, options, opened_path TSRMLS_CC);
+ if (zend_hash_find(EG(active_symbol_table), "http_response_header",
+ sizeof("http_response_header"), (void **) &response_header_new) == SUCCESS) {
+ entryp = &entry;
+ MAKE_STD_ZVAL(entry);
+ ZVAL_EMPTY_STRING(entry);
+ zend_hash_next_index_insert(Z_ARRVAL_P(response_header), entryp, sizeof(zval *), NULL);
+ zend_hash_internal_pointer_reset(Z_ARRVAL_PP(response_header_new));
+ while (zend_hash_get_current_data(Z_ARRVAL_PP(response_header_new), (void **)&entryp) == SUCCESS) {
+ zval_add_ref(entryp);
+ zend_hash_next_index_insert(Z_ARRVAL_P(response_header), entryp, sizeof(zval *), NULL);
+ zend_hash_move_forward(Z_ARRVAL_PP(response_header_new));
+ }
+ }
+ }
+ else if (options & REPORT_ERRORS)
+ zend_error(E_WARNING, "HTTP request failed!");
+ }
+out:
+ if (http_header_line)
+ efree(http_header_line);
+ if (scratch)
+ efree(scratch);
+ php_url_free(resource);
+
+ if (response_header)
+ ZEND_SET_SYMBOL(EG(active_symbol_table), "http_response_header", response_header);
+
+ return stream;
+}
+
+
+
+#endif
+
+
/* {{{ php_fopen_url_wrap_http
*/
Index: ext/standard/php_fopen_wrappers.h
===================================================================
RCS file: /repository/php4/ext/standard/php_fopen_wrappers.h,v
retrieving revision 1.5
diff -u -w -B -b -r1.5 php_fopen_wrappers.h
--- ext/standard/php_fopen_wrappers.h 11 Dec 2001 15:30:35 -0000 1.5
+++ ext/standard/php_fopen_wrappers.h 18 Feb 2002 12:00:57 -0000
@@ -27,4 +27,8 @@
FILE *php_fopen_url_wrap_ftp(const char *, char *, int, int *, int *, char ** TSRMLS_DC);
FILE *php_fopen_url_wrap_php(const char *, char *, int, int *, int *, char ** TSRMLS_DC);
+#if HAVE_PHP_STREAM
+php_stream * php_stream_url_wrap_http(char * path, char * mode, int options, char ** opened_path TSRMLS_DC);
+#endif
+
#endif
Index: main/fopen_wrappers.h
===================================================================
RCS file: /repository/php4/main/fopen_wrappers.h,v
retrieving revision 1.32
diff -u -w -B -b -r1.32 fopen_wrappers.h
--- main/fopen_wrappers.h 1 Feb 2002 20:04:14 -0000 1.32
+++ main/fopen_wrappers.h 18 Feb 2002 12:01:00 -0000
@@ -33,6 +33,8 @@
#endif
#define ENFORCE_SAFE_MODE 4
+#define REPORT_ERRORS 8
+
#ifdef PHP_WIN32
# define SOCK_ERR INVALID_SOCKET
# define SOCK_CONN_ERR SOCKET_ERROR
Index: main/main.c
===================================================================
RCS file: /repository/php4/main/main.c,v
retrieving revision 1.422
diff -u -w -B -b -r1.422 main.c
--- main/main.c 14 Feb 2002 20:16:05 -0000 1.422
+++ main/main.c 18 Feb 2002 12:01:00 -0000
@@ -73,6 +73,7 @@
#include "php_content_types.h"
#include "php_ticks.h"
#include "php_logos.h"
+#include "php_streams.h"
#include "SAPI.h"
/* }}} */
@@ -900,6 +901,16 @@
return FAILURE;
}
+#if HAVE_PHP_STREAM
+ /* initialize stream wrappers registry
+ * (this uses configuration parameters from php.ini)
+ */
+ if (php_init_stream_wrappers(TSRMLS_C) == FAILURE) {
+ php_printf("PHP: Unable to initialize stream url wrappers.\n");
+ return FAILURE;
+ }
+#endif
+
/* initialize registry for images to be used in phpinfo()
(this uses configuration parameters from php.ini)
*/
@@ -998,6 +1009,11 @@
sapi_flush(TSRMLS_C);
zend_shutdown(TSRMLS_C);
+
+#if HAVE_PHP_STREAM
+ php_shutdown_stream_wrappers(TSRMLS_C);
+#endif
+
php_shutdown_fopen_wrappers(TSRMLS_C);
php_shutdown_info_logos();
UNREGISTER_INI_ENTRIES();
Index: main/network.c
===================================================================
RCS file: /repository/php4/main/network.c,v
retrieving revision 1.29
diff -u -w -B -b -r1.29 network.c
--- main/network.c 12 Feb 2002 11:00:15 -0000 1.29
+++ main/network.c 18 Feb 2002 12:01:00 -0000
@@ -17,6 +17,9 @@
*/
/* $Id: network.c,v 1.29 2002/02/12 11:00:15 sas Exp $ */
+#define PHP_SOCK_CHUNK_SIZE 8192
+#define MAX_CHUNKS_PER_READ 10
+
#include "php.h"
#ifdef PHP_WIN32
@@ -407,6 +410,396 @@
}
}
/* }}} */
+
+#if HAVE_PHP_STREAM
+
+PHPAPI php_stream * php_stream_sock_open_from_socket(int socket, int persistent)
+{
+ php_stream * stream;
+ php_netstream_data_t * sock;
+
+ sock = pemalloc(sizeof(php_netstream_data_t), persistent);
+ memset(sock, 0, sizeof(php_netstream_data_t));
+
+ sock->is_blocked = 1;
+ sock->chunk_size = PHP_SOCK_CHUNK_SIZE;
+ sock->timeout.tv_sec = -1;
+ sock->socket = socket;
+
+ stream = php_stream_alloc(&php_stream_socket_ops, sock, persistent, "r+");
+
+ if (stream == NULL)
+ pefree(sock, persistent);
+
+ return stream;
+}
+
+PHPAPI php_stream * php_stream_sock_open_host(const char * host, unsigned short port,
+ int socktype, int timeout, int persistent)
+{
+ int socket;
+
+ socket = php_hostconnect(host, port, socktype, timeout);
+
+ if (socket == -1)
+ return NULL;
+
+ return php_stream_sock_open_from_socket(socket, persistent);
+}
+
+PHPAPI php_stream * php_stream_sock_open_unix(const char * path, int persistent, struct timeval * timeout)
+{
+#if defined(AF_UNIX)
+ int socketd;
+ struct sockaddr_un unix_addr;
+
+ socketd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (socketd == SOCK_ERR)
+ return NULL;
+
+ memset(&unix_addr, 0, sizeof(unix_addr));
+ unix_addr.sun_family = AF_UNIX;
+ strlcpy(unix_addr.sun_path, path, sizeof(unix_addr.sun_path));
+
+ if (php_connect_nonb(socketd, (struct sockaddr *) &unix_addr, sizeof(unix_addr), timeout) == SOCK_CONN_ERR)
+ return NULL;
+
+ return php_stream_sock_open_from_socket(socketd, persistent);
+#else
+ return NULL;
+#endif
+}
+
+#if HAVE_OPENSSL_EXT
+PHPAPI int php_stream_sock_ssl_activate_with_method(php_stream * stream, int activate, SSL_METHOD * method)
+{
+ php_netstream_data_t * sock = (php_netstream_data_t*)stream->abstract;
+ SSL_CTX * ctx = NULL;
+
+ if (!php_stream_is(stream, PHP_STREAM_IS_SOCKET))
+ return FAILURE;
+
+ if (activate == sock->ssl_active)
+ return SUCCESS; /* already in desired mode */
+
+ if (activate && sock->ssl_handle == NULL) {
+ ctx = SSL_CTX_new(method);
+ if (ctx == NULL)
+ return FAILURE;
+
+ sock->ssl_handle = SSL_new(ctx);
+ if (sock->ssl_handle == NULL) {
+ SSL_CTX_free(ctx);
+ return FAILURE;
+ }
+
+ SSL_set_fd(sock->ssl_handle, sock->socket);
+ }
+
+ if (activate) {
+ if (SSL_connect(sock->ssl_handle) <= 0) {
+ SSL_shutdown(sock->ssl_handle);
+ return FAILURE;
+ }
+ sock->ssl_active = activate;
+ }
+ else {
+ SSL_shutdown(sock->ssl_handle);
+ sock->ssl_active = 0;
+ }
+ return SUCCESS;
+}
+#endif
+
+PHPAPI void php_stream_sock_set_timeout(php_stream * stream, struct timeval *timeout)
+{
+ php_netstream_data_t * sock = (php_netstream_data_t*)stream->abstract;
+
+ if (!php_stream_is(stream, PHP_STREAM_IS_SOCKET))
+ return;
+
+ sock->timeout = *timeout;
+ sock->timeout_event = 0;
+}
+
+PHPAPI int php_stream_sock_set_blocking(php_stream * stream, int mode)
+{
+ int oldmode;
+ php_netstream_data_t * sock = (php_netstream_data_t*)stream->abstract;
+
+ if (!php_stream_is(stream, PHP_STREAM_IS_SOCKET))
+ return 0;
+
+ oldmode = sock->is_blocked;
+ sock->is_blocked = mode;
+
+ return oldmode;
+}
+
+
+#define TOREAD(sock) ((sock)->writepos - (sock)->readpos)
+#define READPTR(sock) ((sock)->readbuf + (sock)->readpos)
+#define WRITEPTR(sock) ((sock)->readbuf + (sock)->writepos)
+
+static size_t php_sockop_write(php_stream * stream, const char * buf, size_t count)
+{
+ php_netstream_data_t * sock = (php_netstream_data_t*)stream->abstract;
+#if HAVE_OPENSSL_EXT
+ if (sock->ssl_active)
+ return SSL_write(sock->ssl_handle, buf, count);
+#endif
+ return send(sock->socket, buf, count, 0);
+}
+static void php_sock_stream_wait_for_data(php_stream * stream, php_netstream_data_t * sock)
+{
+ fd_set fdr, tfdr;
+ int retval;
+ struct timeval timeout, *ptimeout;
+
+ FD_ZERO(&fdr);
+ FD_SET(sock->socket, &fdr);
+ sock->timeout_event = 0;
+
+ if (sock->timeout.tv_sec == -1)
+ ptimeout = NULL;
+ else
+ ptimeout = &timeout;
+
+ while(1) {
+ tfdr = fdr;
+ timeout = sock->timeout;
+
+ retval = select(sock->socket + 1, &tfdr, NULL, NULL, ptimeout);
+
+ if (retval == 0)
+ sock->timeout_event = 1;
+
+ if (retval >= 0)
+ break;
+ }
+}
+
+static size_t php_sock_stream_read_internal(php_stream * stream, php_netstream_data_t * sock)
+{
+ char buf[PHP_SOCK_CHUNK_SIZE];
+ int nr_bytes;
+ size_t nr_read = 0;
+
+ /* For blocking sockets, we wait until there is some
+ data to read (real data or EOF)
+
+ Otherwise, recv() may time out and return 0 and
+ therefore sock->eof would be set errornously.
+ */
+
+
+ if(sock->is_blocked) {
+ php_sock_stream_wait_for_data(stream, sock);
+ if (sock->timeout_event)
+ return 0;
+ }
+
+ /* read at a maximum sock->chunk_size */
+#if HAVE_OPENSSL_EXT
+ if (sock->ssl_active)
+ nr_bytes = SSL_read(sock->ssl_handle, buf, sock->chunk_size);
+ else
+#endif
+ nr_bytes = recv(sock->socket, buf, sock->chunk_size, 0);
+ if(nr_bytes > 0) {
+ if(sock->writepos + nr_bytes > sock->readbuflen) {
+ sock->readbuflen += sock->chunk_size;
+ sock->readbuf = perealloc(sock->readbuf, sock->readbuflen,
+ php_stream_is_persistent(stream));
+ }
+ 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;
+ }
+
+ return nr_read;
+
+}
+
+static size_t php_sock_stream_read(php_stream * stream, php_netstream_data_t * 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 = php_sock_stream_read_internal(stream, sock);
+ if(nr_bytes == 0) break;
+ nr_read += nr_bytes;
+ }
+
+ return nr_read;
+}
+
+static size_t php_sockop_read(php_stream * stream, char * buf, size_t count)
+{
+ php_netstream_data_t * sock = (php_netstream_data_t*)stream->abstract;
+ size_t ret = 0;
+
+ if (sock->is_blocked) {
+ while(!sock->eof && TOREAD(sock) < count && !sock->timeout_event)
+ php_sock_stream_read_internal(stream, sock);
+ }
+ else
+ php_sock_stream_read(stream, sock);
+
+ if(count < 0)
+ return ret;
+
+ ret = MIN(TOREAD(sock), count);
+ if (ret) {
+ memcpy(buf, READPTR(sock), ret);
+ sock->readpos += ret;
+ }
+
+ return ret;
+}
+
+static int php_sockop_close(php_stream * stream)
+{
+ php_netstream_data_t * sock = (php_netstream_data_t*)stream->abstract;
+
+#if HAVE_OPENSSL_EXT
+ if (sock->ssl_active) {
+ SSL_shutdown(sock->ssl_handle);
+ sock->ssl_active = 0;
+ SSL_free(sock->ssl_handle);
+ sock->ssl_handle = NULL;
+ }
+#endif
+
+ shutdown(sock->socket, 0);
+ closesocket(sock->socket);
+
+ if (sock->readbuf)
+ pefree(sock->readbuf, php_stream_is_persistent(stream));
+
+ pefree(sock, php_stream_is_persistent(stream));
+
+ return 0;
+}
+
+static int php_sockop_flush(php_stream * stream)
+{
+ php_netstream_data_t * sock = (php_netstream_data_t*)stream->abstract;
+ return fsync(sock->socket);
+}
+
+static int php_sockop_cast(php_stream * stream, int castas, void ** ret)
+{
+ php_netstream_data_t * sock = (php_netstream_data_t*)stream->abstract;
+ TSRMLS_FETCH();
+
+ switch(castas) {
+ case PHP_STREAM_AS_STDIO:
+#if HAVE_OPENSSL_EXT
+ if (sock->ssl_active)
+ return FAILURE;
+#endif
+ if (ret) {
+ /* DANGER!: data buffered in stream->readbuf will be forgotten! */
+ if (TOREAD(sock) > 0)
+ zend_error(E_WARNING, "%s(): buffered data lost during conversion to FILE*!", get_active_function_name(TSRMLS_C));
+ *ret = fdopen(sock->socket, stream->mode);
+ if (*ret)
+ return SUCCESS;
+ return FAILURE;
+ }
+ return SUCCESS;
+ case PHP_STREAM_AS_FD:
+ case PHP_STREAM_AS_SOCKETD:
+#if HAVE_OPENSSL_EXT
+ if (sock->ssl_active)
+ return FAILURE;
+#endif
+ if (ret)
+ *ret = (void*)sock->socket;
+ return SUCCESS;
+ default:
+ return FAILURE;
+ }
+}
+
+#define SEARCHCR() do { \
+ if (TOREAD(sock)) { \
+ for (p = READPTR(sock), pe = p + MIN(TOREAD(sock), maxlen); \
+ *p != '\n'; ) \
+ if (++p >= pe) { \
+ p = NULL; \
+ break; \
+ } \
+ } else \
+ p = NULL; \
+} while (0)
+
+
+static char * php_sockop_gets(php_stream * stream, char *buf, size_t maxlen)
+{
+ php_netstream_data_t * sock = (php_netstream_data_t*)stream->abstract;
+ char *p = NULL, *pe;
+ char *ret = NULL;
+ size_t amount = 0;
+
+ if (maxlen==0) {
+ buf[0] = 0;
+ return buf;
+ }
+
+ SEARCHCR();
+
+ if(!p) {
+ if(sock->is_blocked) {
+ while(!p && !sock->eof && !sock->timeout_event && TOREAD(sock) < maxlen) {
+ php_sock_stream_read_internal(stream, sock);
+ SEARCHCR();
+ }
+ } else {
+ php_sock_stream_read(stream, sock);
+ SEARCHCR();
+ }
+ }
+
+ if(p) {
+ amount = (ptrdiff_t) p - (ptrdiff_t) READPTR(sock) + 1;
+ } else {
+ amount = TOREAD(sock);
+ }
+
+ amount = MIN(amount, maxlen);
+
+ 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;
+ }
+
+ return ret;
+}
+
+php_stream_ops php_stream_socket_ops = {
+ php_sockop_write, php_sockop_read,
+ php_sockop_close, php_sockop_flush,
+ NULL, php_sockop_gets,
+ php_sockop_cast,
+ "socket"
+};
+
+
+#endif
+
/*
* Local variables:
Index: main/php_network.h
===================================================================
RCS file: /repository/php4/main/php_network.h,v
retrieving revision 1.11
diff -u -w -B -b -r1.11 php_network.h
--- main/php_network.h 10 Feb 2002 12:35:29 -0000 1.11
+++ main/php_network.h 18 Feb 2002 12:01:01 -0000
@@ -27,8 +27,17 @@
# undef FD_SETSIZE
# include "arpa/inet.h"
# define socklen_t unsigned int
+#else
+# undef closesocket
+# define closesocket close
+#endif
+
+#ifndef HAVE_SHUTDOWN
+#undef shutdown
+#define shutdown(s,n) /* nothing */
#endif
+
#ifdef HAVE_NETINET_IN_H
# include
#endif
@@ -41,6 +50,10 @@
#include
#endif
+#if HAVE_OPENSSL_EXT
+#include
+#endif
+
#ifdef HAVE_SOCKADDR_STORAGE
typedef struct sockaddr_storage php_sockaddr_storage;
#else
@@ -55,6 +68,45 @@
PHPAPI int php_connect_nonb(int sockfd, const struct sockaddr *addr, socklen_t addrlen, struct timeval *timeout);
void php_any_addr(int family, php_sockaddr_storage *addr, unsigned short port);
int php_sockaddr_size(php_sockaddr_storage *addr);
+
+#if HAVE_PHP_STREAM
+struct _php_netstream_data_t {
+ int socket;
+ unsigned char *readbuf;
+ size_t readbuflen;
+ size_t readpos;
+ size_t writepos;
+ char eof;
+ char is_blocked;
+ size_t chunk_size;
+ struct timeval timeout;
+ char timeout_event;
+#if HAVE_OPENSSL_EXT
+ /* openssl specific bits here */
+ SSL * ssl_handle;
+ int ssl_active;
+#endif
+};
+typedef struct _php_netstream_data_t php_netstream_data_t;
+
+extern php_stream_ops php_stream_socket_ops;
+#define PHP_STREAM_IS_SOCKET (&php_stream_socket_ops)
+
+PHPAPI php_stream * php_stream_sock_open_from_socket(int socket, int persistent);
+/* open a connection to a host using php_hostconnect and return a stream */
+PHPAPI php_stream * php_stream_sock_open_host(const char * host, unsigned short port,
+ int socktype, int timeout, int persistent);
+PHPAPI php_stream * php_stream_sock_open_unix(const char * path, int persistent, struct timeval * timeout);
+
+PHPAPI void php_stream_sock_set_timeout(php_stream * stream, struct timeval *timeout);
+PHPAPI int php_stream_sock_set_blocking(php_stream * stream, int mode);
+
+#if HAVE_OPENSSL_EXT
+PHPAPI int php_stream_sock_ssl_activate_with_method(php_stream * stream, int activate, SSL_METHOD * method);
+#define php_stream_sock_ssl_activate(stream, activate) php_stream_sock_ssl_activate_with_method((stream), (activate), SSLv23_client_method())
+
+#endif
+#endif
#endif /* _PHP_NETWORK_H */
Index: main/php_streams.h
===================================================================
RCS file: /repository/php4/main/php_streams.h,v
retrieving revision 1.5
diff -u -w -B -b -r1.5 php_streams.h
--- main/php_streams.h 11 Dec 2001 15:31:05 -0000 1.5
+++ main/php_streams.h 18 Feb 2002 12:01:01 -0000
@@ -69,15 +69,19 @@
PHPAPI off_t php_stream_tell(php_stream * stream);
PHPAPI size_t php_stream_read(php_stream * stream, char * buf, size_t count);
PHPAPI size_t php_stream_write(php_stream * stream, const char * buf, size_t count);
+#define php_stream_write_string(stream, str) php_stream_write(stream, str, strlen(str))
PHPAPI int php_stream_eof(php_stream * stream);
PHPAPI int php_stream_getc(php_stream * stream);
PHPAPI int php_stream_flush(php_stream * stream);
PHPAPI char *php_stream_gets(php_stream * stream, char *buf, size_t maxlen);
-/* operations for a stdio FILE; the FILE * must be placed in stream->abstract */
+/* operations for a stdio FILE; use the php_stream_fopen_XXX funcs below */
extern php_stream_ops php_stream_stdio_ops;
/* like fopen, but returns a stream */
-PHPAPI php_stream * php_stream_fopen(const char * filename, const char * mode);
+PHPAPI php_stream * php_stream_fopen(const char * filename, const char * mode, char **opened_path TSRMLS_DC);
+PHPAPI php_stream * php_stream_fopen_with_path(char * filename, char * mode, char * path, char **opened_path TSRMLS_DC);
+PHPAPI php_stream * php_stream_fopen_from_file(FILE * file, const char * mode);
+PHPAPI php_stream * php_stream_fopen_from_pipe(FILE * file, const char * mode);
/* coerce the stream into some other form */
/* cast as a stdio FILE * */
@@ -93,7 +97,21 @@
/* use this to check if a stream is of a particular type:
* PHPAPI int php_stream_is(php_stream * stream, php_stream_ops * ops); */
-#define php_stream_is(stream, anops) (stream->ops == anops)
+#define php_stream_is(stream, anops) ((stream)->ops == anops)
+#define PHP_STREAM_IS_STDIO &php_stream_stdio_ops
+
+#define php_stream_is_persistent(stream) (stream)->is_persistent
+
+/* Wrappers support */
+/* options uses the IGNORE_URL family of defines from fopen_wrappers.h */
+typedef php_stream * (*php_stream_factory_func_t)(char * filename, char * mode, int options, char ** opened_path TSRMLS_DC);
+
+int php_init_stream_wrappers(TSRMLS_D);
+int php_shutdown_stream_wrappers(TSRMLS_D);
+PHPAPI int php_register_url_stream_wrapper(char * protocol, php_stream_factory_func_t wrapper TSRMLS_DC);
+PHPAPI int php_unregister_url_stream_wrapper(char * protocol, php_stream_factory_func_t wrapper TSRMLS_DC);
+
+PHPAPI php_stream * php_stream_open_wrapper(char * path, char * mode, int options, char ** opened_path TSRMLS_DC);
#endif /* HAVE_PHP_STREAM */
Index: main/streams.c
===================================================================
RCS file: /repository/php4/main/streams.c,v
retrieving revision 1.8
diff -u -w -B -b -r1.8 streams.c
--- main/streams.c 11 Dec 2001 15:31:05 -0000 1.8
+++ main/streams.c 18 Feb 2002 12:01:01 -0000
@@ -14,11 +14,18 @@
+----------------------------------------------------------------------+
| Authors: |
| Wez Furlong (wez@thebrainroom.com) |
+ | Borrowed code from: |
+ | Rasmus Lerdorf |
+ | Jim Winstead |
+----------------------------------------------------------------------+
*/
+/* define this to allow us to fallback on older fopen wrapper handlers */
+#define STREAMS_SUPPORT_FOPEN_WRAPPER 1
+
#define _GNU_SOURCE
#include "php.h"
+#include "php_globals.h"
#if HAVE_PHP_STREAM
@@ -28,18 +35,10 @@
#include "build-defs.h"
#endif
-#define MAX_CHUNK_SIZE 8192
-
-#define TOREAD(stream) ((stream)->readbuf.writepos - (stream)->readbuf.readpos)
-#define TOWRITE(stream) ((stream)->readbuf.writepos - (stream)->readbuf.readpos)
-
-#define READPTR(stream) ((stream)->readbuf.buffer + (stream)->readbuf.readpos)
-#define WRITEPTR(stream) ((stream)->readbuf.buffer + (stream)->readbuf.writepos)
-
-#define READ_MAX(stream, max) if (stream->is_blocked) stream_read_total(sock, max); else stream_readahead(sock)
+static HashTable url_stream_wrappers_hash;
/* allocate a new stream for a particular ops */
-PHPAPI php_stream * php_stream_alloc(php_stream_ops * ops, void * abstract, int persistent, const char * mode)
+PHPAPI php_stream * php_stream_alloc(php_stream_ops * ops, void * abstract, int persistent, const char * mode) /* {{{ */
{
php_stream * ret;
@@ -55,8 +54,9 @@
return ret;
}
+/* }}} */
-PHPAPI int php_stream_free(php_stream * stream, int call_dtor)
+PHPAPI int php_stream_free(php_stream * stream, int call_dtor) /* {{{ */
{
int ret = 1;
@@ -87,7 +87,9 @@
return ret;
}
+/* }}} */
+/* {{{ generic stream operations */
PHPAPI size_t php_stream_read(php_stream * stream, char * buf, size_t size)
{
return stream->ops->read(stream, buf, size);
@@ -148,13 +150,6 @@
PHPAPI size_t php_stream_write(php_stream * stream, const char * buf, size_t count)
{
- if (strchr(stream->mode, 'w') == NULL) {
- TSRMLS_FETCH();
-
- zend_error(E_WARNING, "%s(): stream was not opened for writing", get_active_function_name(TSRMLS_C));
- return 0;
- }
-
return stream->ops->write(stream, buf, count);
}
@@ -175,44 +170,101 @@
zend_error(E_WARNING, "streams of type %s do not support seeking", stream->ops->label);
return -1;
}
+/* }}} */
+
+
+
+/* {{{ ------- STDIO stream implementation -------*/
-/*------- STDIO stream implementation -------*/
+typedef struct {
+ FILE * file;
+ int is_pipe; /* use pclose */
+#if HAVE_FLUSHIO
+ char last_op;
+#endif
+} php_stdio_stream_data;
+
+PHPAPI php_stream * php_stream_fopen_from_file(FILE * file, const char * mode)
+{
+ php_stdio_stream_data * self;
+ self = emalloc(sizeof(*self));
+ self->file = file;
+ self->is_pipe = 0;
+ return php_stream_alloc(&php_stream_stdio_ops, self, 0, mode);
+}
+
+PHPAPI php_stream * php_stream_fopen_from_pipe(FILE * file, const char * mode)
+{
+ php_stdio_stream_data * self;
+
+ self = emalloc(sizeof(*self));
+ self->file = file;
+ self->is_pipe = 1;
+ return php_stream_alloc(&php_stream_stdio_ops, self, 0, mode);
+}
static size_t php_stdiop_write(php_stream * stream, const char * buf, size_t count)
{
- return fwrite(buf, 1, count, (FILE*)stream->abstract);
+ php_stdio_stream_data * data = (php_stdio_stream_data*)stream->abstract;
+
+#if HAVE_FLUSHIO
+ if (data->last_op == 'r')
+ fseek(data->file, 0, SEEK_CUR);
+ data->last_op = 'w';
+#endif
+
+ return fwrite(buf, 1, count, data->file);
}
static size_t php_stdiop_read(php_stream * stream, char * buf, size_t count)
{
+ php_stdio_stream_data * data = (php_stdio_stream_data*)stream->abstract;
+
if (buf == NULL && count == 0) {
/* check for EOF condition */
- if (feof((FILE*)stream->abstract)) {
+ if (feof(data->file)) {
return EOF;
}
return 0;
}
- return fread(buf, 1, count, (FILE*)stream->abstract);
+
+#if HAVE_FLUSHIO
+ if (data->last_op == 'w')
+ fseek(data->file, 0, SEEK_CUR);
+ data->last_op = 'r';
+#endif
+
+ return fread(buf, 1, count, ((php_stdio_stream_data*)stream->abstract)->file);
}
static int php_stdiop_close(php_stream * stream)
{
- return fclose((FILE*)stream->abstract);
+ int ret;
+ php_stdio_stream_data * data = (php_stdio_stream_data*)stream->abstract;
+
+ if (data->is_pipe)
+ ret = pclose(data->file);
+ else
+ ret = fclose(data->file);
+
+ efree(data);
+
+ return ret;
}
static int php_stdiop_flush(php_stream * stream)
{
- return fflush((FILE*)stream->abstract);
+ return fflush(((php_stdio_stream_data*)stream->abstract)->file);
}
static int php_stdiop_seek(php_stream * stream, off_t offset, int whence)
{
- return fseek((FILE*)stream->abstract, offset, whence);
+ return fseek(((php_stdio_stream_data*)stream->abstract)->file, offset, whence);
}
static char * php_stdiop_gets(php_stream * stream, char * buf, size_t size)
{
- return fgets(buf, size, (FILE*)stream->abstract);
+ return fgets(buf, size, ((php_stdio_stream_data*)stream->abstract)->file);
}
static int php_stdiop_cast(php_stream * stream, int castas, void ** ret)
{
@@ -221,11 +273,11 @@
switch (castas) {
case PHP_STREAM_AS_STDIO:
if (ret)
- *ret = stream->abstract;
+ *ret = ((php_stdio_stream_data*)stream->abstract)->file;
return SUCCESS;
case PHP_STREAM_AS_FD:
- fd = fileno((FILE*)stream->abstract);
+ fd = fileno(((php_stdio_stream_data*)stream->abstract)->file);
if (fd < 0)
return FAILURE;
if (ret)
@@ -243,21 +295,153 @@
"STDIO"
};
-PHPAPI php_stream * php_stream_fopen(const char * filename, const char * mode)
+PHPAPI php_stream * php_stream_fopen_with_path(char * filename, char * mode, char * path, char **opened_path TSRMLS_DC) /* {{{ */
{
- FILE * fp = fopen(filename, mode);
+ /* code ripped off from fopen_wrappers.c */
+ char *pathbuf, *ptr, *end;
+ char *exec_fname;
+ char trypath[MAXPATHLEN];
+ struct stat sb;
+ php_stream *stream;
+ int path_length;
+ int filename_length;
+ int exec_fname_length;
+
+ if (opened_path) {
+ *opened_path = NULL;
+ }
+
+ if(!filename) {
+ return NULL;
+ }
+
+ filename_length = strlen(filename);
+
+ /* Relative path open */
+ if (*filename == '.') {
+ if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) {
+ return NULL;
+ }
+ return php_stream_fopen(filename, mode, opened_path TSRMLS_CC);
+ }
+
+ /*
+ * files in safe_mode_include_dir (or subdir) are excluded from
+ * safe mode GID/UID checks
+ */
+
+ /* Absolute path open */
+ if (IS_ABSOLUTE_PATH(filename, filename_length)) {
+ if ((php_check_safe_mode_include_dir(filename TSRMLS_CC)) == 0)
+ /* filename is in safe_mode_include_dir (or subdir) */
+ return php_stream_fopen(filename, mode, opened_path TSRMLS_CC);
+
+ if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM)))
+ return NULL;
+
+ return php_stream_fopen(filename, mode, opened_path TSRMLS_CC);
+ }
+
+ if (!path || (path && !*path)) {
+ if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) {
+ return NULL;
+ }
+ return php_stream_fopen(filename, mode, opened_path TSRMLS_CC);
+ }
+
+ /* check in provided path */
+ /* append the calling scripts' current working directory
+ * as a fall back case
+ */
+ if (zend_is_executing(TSRMLS_C)) {
+ exec_fname = zend_get_executed_filename(TSRMLS_C);
+ exec_fname_length = strlen(exec_fname);
+ path_length = strlen(path);
+
+ while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
+ if ((exec_fname && exec_fname[0] == '[')
+ || exec_fname_length<=0) {
+ /* [no active file] or no path */
+ pathbuf = estrdup(path);
+ } else {
+ pathbuf = (char *) emalloc(exec_fname_length + path_length +1 +1);
+ memcpy(pathbuf, path, path_length);
+ pathbuf[path_length] = DEFAULT_DIR_SEPARATOR;
+ memcpy(pathbuf+path_length+1, exec_fname, exec_fname_length);
+ pathbuf[path_length + exec_fname_length +1] = '\0';
+ }
+ } else {
+ pathbuf = estrdup(path);
+ }
+
+ ptr = pathbuf;
+
+ while (ptr && *ptr) {
+ end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
+ if (end != NULL) {
+ *end = '\0';
+ end++;
+ }
+ snprintf(trypath, MAXPATHLEN, "%s/%s", ptr, filename);
+ if (PG(safe_mode)) {
+ if (VCWD_STAT(trypath, &sb) == 0) {
+ /* file exists ... check permission */
+ if ((php_check_safe_mode_include_dir(trypath TSRMLS_CC) == 0) ||
+ php_checkuid(trypath, mode, CHECKUID_CHECK_MODE_PARAM))
+ /* UID ok, or trypath is in safe_mode_include_dir */
+ stream = php_stream_fopen(trypath, mode, opened_path TSRMLS_CC);
+ else
+ stream = NULL;
+
+ efree(pathbuf);
+ return stream;
+ }
+ }
+ stream = php_stream_fopen(trypath, mode, opened_path TSRMLS_CC);
+ if (stream) {
+ efree(pathbuf);
+ return stream;
+ }
+ ptr = end;
+ } /* end provided path */
+
+ efree(pathbuf);
+ return NULL;
+
+}
+/* }}} */
+
+PHPAPI php_stream * php_stream_fopen(const char * filename, const char * mode, char **opened_path TSRMLS_DC)
+{
+ FILE * fp;
+ char * realpath;
+
+ realpath = expand_filepath(filename, NULL TSRMLS_C);
+
+ fp = fopen(realpath, mode);
if (fp) {
- php_stream * ret = php_stream_alloc(&php_stream_stdio_ops, fp, 0, mode);
+ php_stream * ret = php_stream_fopen_from_file(fp, mode);
+
+ if (ret) {
+ if (opened_path) {
+ *opened_path = realpath;
+ realpath = NULL;
+ }
+ if (realpath)
+ efree(realpath);
- if (ret)
return ret;
+ }
fclose(fp);
}
+ efree(realpath);
return NULL;
}
+/* }}} */
+/* {{{ STDIO with fopencookie */
#if HAVE_FOPENCOOKIE
static ssize_t stream_cookie_reader(void *cookie, char *buffer, size_t size)
{
@@ -287,8 +471,9 @@
#else
/* TODO: use socketpair() to emulate fopencookie, as suggested by Hartmut ? */
#endif
+/* }}} */
-PHPAPI int php_stream_cast(php_stream * stream, int castas, void ** ret, int show_err)
+PHPAPI int php_stream_cast(php_stream * stream, int castas, void ** ret, int show_err) /* {{{ */
{
if (castas == PHP_STREAM_AS_STDIO) {
if (stream->stdiocast) {
@@ -355,7 +540,122 @@
return SUCCESS;
+} /* }}} */
+
+int php_init_stream_wrappers(TSRMLS_D)
+{
+ if (PG(allow_url_fopen))
+ return zend_hash_init(&url_stream_wrappers_hash, 0, NULL, NULL, 1);
+ return SUCCESS;
}
+
+int php_shutdown_stream_wrappers(TSRMLS_D)
+{
+ if (PG(allow_url_fopen))
+ zend_hash_destroy(&url_stream_wrappers_hash);
+ return SUCCESS;
+}
+
+PHPAPI int php_register_url_stream_wrapper(char * protocol, php_stream_factory_func_t wrapper TSRMLS_DC)
+{
+ if (PG(allow_url_fopen))
+ return zend_hash_add(&url_stream_wrappers_hash, protocol, strlen(protocol), &wrapper, sizeof(wrapper), NULL);
+ return FAILURE;
+}
+PHPAPI int php_unregister_url_stream_wrapper(char * protocol, php_stream_factory_func_t wrapper TSRMLS_DC)
+{
+ if (PG(allow_url_fopen))
+ return zend_hash_del(&url_stream_wrappers_hash, protocol, strlen(protocol));
+ return SUCCESS;
+}
+
+static php_stream * php_stream_open_url(char * path, char * mode, int options, char ** opened_path TSRMLS_DC)
+{
+ php_stream_factory_func_t * wrapper;
+ const char * p, *protocol = NULL;
+ int n = 0;
+
+ for (p = path; isalnum((int)*p); p++)
+ n++;
+
+ if ((*p == ':') && (n > 1))
+ protocol = path;
+
+ if (protocol) {
+#ifdef STREAMS_SUPPORT_FOPEN_WRAPPER
+ FILE * fallback;
+ int issock;
+ int socketd;
+#endif
+
+ if (FAILURE == zend_hash_find(&url_stream_wrappers_hash, (char*)protocol, n, (void**)&wrapper)) {
+ wrapper = NULL;
+ protocol = NULL;
+ }
+ if (wrapper)
+ return (*wrapper)(path, mode, options, opened_path TSRMLS_CC);
+
+ /* no luck there. We could try the regular fopen wrappers stuff here */
+#ifdef STREAMS_SUPPORT_FOPEN_WRAPPER
+ fallback = php_fopen_wrapper(path, mode, options, &issock, &socketd, opened_path TSRMLS_CC);
+
+ if (issock)
+ return php_stream_sock_open_from_socket(socketd, 0);
+
+ if (fallback)
+ return php_stream_fopen_from_file(fallback, mode);
+#endif
+ }
+
+ if (!protocol || !strncasecmp(protocol, "file", n)) {
+ if (protocol && path[n+1] == '/' && path[n+2] == '/') {
+ zend_error(E_WARNING, "remote host file access not supported, %s", path);
+ return NULL;
+ }
+ if (protocol)
+ path += n + 1;
+
+ /* fall back on regular file access */
+ return php_stream_open_wrapper(path, mode, (options & ~REPORT_ERRORS) | IGNORE_URL,
+ opened_path TSRMLS_CC);
+ }
+ return NULL;
+}
+
+PHPAPI php_stream * php_stream_open_wrapper(char * path, char * mode, int options, char ** opened_path TSRMLS_DC)
+{
+ php_stream * stream = NULL;
+
+ if (opened_path)
+ *opened_path = NULL;
+
+ if (!path || !*path)
+ return NULL;
+
+ if (PG(allow_url_fopen) && !(options & IGNORE_URL)) {
+ stream = php_stream_open_url(path, mode, options, opened_path TSRMLS_CC);
+ goto out;
+ }
+
+ if ((options & USE_PATH) && PG(include_path) != NULL) {
+ stream = php_stream_fopen_with_path(path, mode, PG(include_path), opened_path TSRMLS_CC);
+ goto out;
+ }
+
+ if ((options & ENFORCE_SAFE_MODE) && PG(safe_mode) && (!php_checkuid(path, mode, CHECKUID_CHECK_MODE_PARAM)))
+ return NULL;
+
+ stream = php_stream_fopen(path, mode, opened_path TSRMLS_CC);
+out:
+ if (stream == NULL && (options & REPORT_ERRORS)) {
+ char * tmp = estrdup(path);
+ php_strip_url_passwd(tmp);
+ zend_error(E_WARNING, "%s(\"%s\") - %s", get_active_function_name(TSRMLS_CC), tmp, strerror(errno));
+ efree(tmp);
+ }
+ return stream;
+}
+
#endif
/*
Index: tests/strings/003.phpt
===================================================================
RCS file: /repository/php4/tests/strings/003.phpt,v
retrieving revision 1.3
diff -u -w -B -b -r1.3 003.phpt
--- tests/strings/003.phpt 21 Mar 2001 12:47:46 -0000 1.3
+++ tests/strings/003.phpt 18 Feb 2002 12:01:09 -0000
@@ -5,9 +5,15 @@
--FILE--
\"&εΔ\n");
-echo htmlentities ("<>\"&εΔ\n");
+$sc_encoded = htmlspecialchars ("<>\"&εΔ\n");
+echo $sc_encoded;
+$ent_encoded = htmlentities ("<>\"&εΔ\n");
+echo $ent_encoded;
+echo html_entity_decode($sc_encoded);
+echo html_entity_decode($ent_encoded);
?>
--EXPECT--
<>"&εΔ
<>"&åÄ
+<>"&εΔ
+<>"&εΔ