summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.in9
-rw-r--r--ext/curl/curl.c9
-rw-r--r--ext/exif/exif.c26
-rw-r--r--ext/ftp/ftp.c24
-rw-r--r--ext/ftp/ftp.h5
-rw-r--r--ext/ftp/php_ftp.c76
-rw-r--r--ext/gd/gd.c99
-rw-r--r--ext/hyperwave/hw.c74
-rw-r--r--ext/interbase/interbase.c31
-rwxr-xr-xext/mailparse/mailparse.c113
-rw-r--r--ext/ming/ming.c39
-rw-r--r--ext/pdf/pdf.c12
-rw-r--r--ext/pgsql/pgsql.c16
-rw-r--r--ext/recode/recode.c25
-rw-r--r--ext/standard/basic_functions.c42
-rw-r--r--ext/standard/exec.c5
-rw-r--r--ext/standard/file.c773
-rw-r--r--ext/standard/file.h15
-rw-r--r--ext/standard/fsock.c717
-rw-r--r--ext/standard/fsock.h42
-rw-r--r--ext/standard/ftp_fopen_wrapper.c146
-rw-r--r--ext/standard/html.c198
-rw-r--r--ext/standard/html.h11
-rw-r--r--ext/standard/http_fopen_wrapper.c255
-rw-r--r--ext/standard/image.c189
-rw-r--r--ext/standard/info.c4
-rw-r--r--ext/standard/php_fopen_wrapper.c39
-rw-r--r--ext/standard/php_fopen_wrappers.h8
-rw-r--r--ext/standard/php_image.h2
-rw-r--r--ext/zlib/php_zlib.h3
-rw-r--r--ext/zlib/zlib.c49
-rw-r--r--ext/zlib/zlib_fopen_wrapper.c126
-rw-r--r--main/fopen_wrappers.c137
-rw-r--r--main/fopen_wrappers.h20
-rw-r--r--main/internal_functions.c.in6
-rw-r--r--main/main.c42
-rw-r--r--main/network.c403
-rw-r--r--main/php_network.h54
-rwxr-xr-xmain/php_streams.h55
-rwxr-xr-xmain/streams.c595
-rw-r--r--tests/strings/003.phpt10
41 files changed, 2356 insertions, 2148 deletions
diff --git a/configure.in b/configure.in
index f0cb00d082..a507735cf2 100644
--- a/configure.in
+++ b/configure.in
@@ -730,15 +730,6 @@ if test "$PHP_DMALLOC" = "yes"; then
])
fi
-# temporary until streams are better integrated
-PHP_ARG_ENABLE(php-streams,whether to enable php streams,
-[ --enable-php-streams Include experimental php streams.
- Do not use unless you are testing the code!])
-
-if test "$PHP_PHP_STREAMS" = "yes"; then
- AC_DEFINE(HAVE_PHP_STREAM, 1, [Whether to use php streams])
-fi
-
AC_CHECK_LIB(crypt, crypt, [
PHP_ADD_LIBRARY(crypt)
PHP_ADD_LIBRARY(crypt, 1)
diff --git a/ext/curl/curl.c b/ext/curl/curl.c
index 41f71b0a3a..2413d8b4e7 100644
--- a/ext/curl/curl.c
+++ b/ext/curl/curl.c
@@ -699,7 +699,14 @@ PHP_FUNCTION(curl_setopt)
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, 1, php_file_le_stream());
+ ZEND_VERIFY_RESOURCE(what);
+
+ if (!php_stream_cast((php_stream*)what, PHP_STREAM_AS_STDIO, (void*)&fp, REPORT_ERRORS))
+ RETURN_FALSE;
if (!fp) {
RETURN_FALSE;
}
diff --git a/ext/exif/exif.c b/ext/exif/exif.c
index bce7512862..0b10231bea 100644
--- a/ext/exif/exif.c
+++ b/ext/exif/exif.c
@@ -3220,8 +3220,8 @@ PHP_FUNCTION(exif_thumbnail)
PHP_FUNCTION(exif_imagetype)
{
zval **arg1;
- FILE *fp;
- int issock=0, socketd=0, rsrc_id;
+ php_stream * stream;
+ int rsrc_id;
int itype = 0;
if (ZEND_NUM_ARGS() != 1)
@@ -3230,27 +3230,15 @@ PHP_FUNCTION(exif_imagetype)
if (zend_get_parameters_ex(1, &arg1) == FAILURE)
WRONG_PARAM_COUNT;
- fp = php_fopen_wrapper(Z_STRVAL_PP(arg1), "rb", IGNORE_PATH|ENFORCE_SAFE_MODE, &issock, &socketd, NULL TSRMLS_CC);
+ stream = php_stream_open_wrapper(Z_STRVAL_PP(arg1), "rb", IGNORE_PATH|ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL TSRMLS_CC);
- if (!fp && !socketd) {
- if (issock != BAD_URL) {
- char *tmp = estrndup(Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1));
- php_strip_url_passwd(tmp);
- php_error(E_WARNING, "getimagetype: Unable to open '%s' for reading.", tmp);
- efree(tmp);
- }
+ if (stream == NULL) {
RETURN_FALSE;
}
- if (issock) {
- int *sock=emalloc(sizeof(int));
- *sock = socketd;
- rsrc_id = ZEND_REGISTER_RESOURCE(NULL, sock, php_file_le_socket());
- } else {
- rsrc_id = ZEND_REGISTER_RESOURCE(NULL, fp, php_file_le_fopen());
- }
+ rsrc_id = ZEND_REGISTER_RESOURCE(NULL, stream, php_file_le_stream());
- itype = itype = php_getimagetype(socketd, fp, issock, NULL);
+ itype = itype = php_getimagetype(stream, NULL);
zend_list_delete(rsrc_id);
@@ -3272,4 +3260,4 @@ PHP_FUNCTION(exif_imagetype)
* vim600: sw=4 ts=4 tw=78 fdm=marker
* vim<600: sw=4 ts=4 tw=78
*/
- \ No newline at end of file
+
diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c
index 3350e86642..4121e8dbf3 100644
--- a/ext/ftp/ftp.c
+++ b/ext/ftp/ftp.c
@@ -55,12 +55,6 @@
#include "ftp.h"
#include "ext/standard/fsock.h"
-/* define closesocket macro for portability */
-#ifndef PHP_WIN32
-#undef closesocket
-#define closesocket close
-#endif
-
/* sends an ftp command, returns true on success, false on error.
* it sends the string "cmd args\r\n" if args is non-null, or
* "cmd\r\n" if args is null
@@ -547,7 +541,7 @@ ftp_pasv(ftpbuf_t *ftp, int pasv)
/* {{{ ftp_get
*/
int
-ftp_get(ftpbuf_t *ftp, FILE *outfp, const char *path, ftptype_t type)
+ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type)
{
databuf_t *data = NULL;
char *ptr;
@@ -585,23 +579,23 @@ ftp_get(ftpbuf_t *ftp, FILE *outfp, const char *path, ftptype_t type)
if (type == FTPTYPE_ASCII) {
for (ptr = data->buf; rcvd; rcvd--, ptr++) {
if (lastch == '\r' && *ptr != '\n')
- putc('\r', outfp);
+ php_stream_putc(outstream, '\r');
if (*ptr != '\r')
- putc(*ptr, outfp);
+ php_stream_putc(outstream, *ptr);
lastch = *ptr;
}
}
else {
- fwrite(data->buf, rcvd, 1, outfp);
+ php_stream_write(outstream, data->buf, rcvd);
}
}
if (type == FTPTYPE_ASCII && lastch == '\r')
- putc('\r', outfp);
+ php_stream_putc(outstream, '\r');
data = data_close(data);
- if (ferror(outfp)) {
+ if (php_stream_error(outstream)) {
goto bail;
}
@@ -619,7 +613,7 @@ bail:
/* {{{ ftp_put
*/
int
-ftp_put(ftpbuf_t *ftp, const char *path, FILE *infp, int insocket, int issock, ftptype_t type)
+ftp_put(ftpbuf_t *ftp, const char *path, php_stream * instream, ftptype_t type)
{
databuf_t *data = NULL;
int size;
@@ -645,7 +639,7 @@ ftp_put(ftpbuf_t *ftp, const char *path, FILE *infp, int insocket, int issock, f
size = 0;
ptr = data->buf;
- while ((ch = FP_FGETC(insocket, infp, issock))!=EOF && !FP_FEOF(insocket, infp, issock)) {
+ while ((ch = php_stream_getc(instream))!=EOF && !php_stream_eof(instream)) {
/* flush if necessary */
if (FTP_BUFSIZE - size < 2) {
if (my_send(ftp, data->fd, data->buf, size) != size)
@@ -666,7 +660,7 @@ ftp_put(ftpbuf_t *ftp, const char *path, FILE *infp, int insocket, int issock, f
if (size && my_send(ftp, data->fd, data->buf, size) != size)
goto bail;
- if (!issock && ferror(infp))
+ if (php_stream_error(instream))
goto bail;
data = data_close(data);
diff --git a/ext/ftp/ftp.h b/ext/ftp/ftp.h
index a44c463461..38b75b1f73 100644
--- a/ext/ftp/ftp.h
+++ b/ext/ftp/ftp.h
@@ -130,14 +130,13 @@ int ftp_pasv(ftpbuf_t *ftp, int pasv);
/* retrieves a file and saves its contents to outfp
* returns true on success, false on error
*/
-int ftp_get(ftpbuf_t *ftp, FILE *outfp, const char *path,
+int ftp_get(ftpbuf_t *ftp, php_stream * outstream, const char *path,
ftptype_t type);
/* stores the data from a file, socket, or process as a file on the remote server
* returns true on success, false on error
*/
-int ftp_put(ftpbuf_t *ftp, const char *path, FILE *infp,
- int insocket, int issock, ftptype_t type);
+int ftp_put(ftpbuf_t *ftp, const char *path, php_stream * instream, ftptype_t type);
/* returns the size of the given file, or -1 on error */
int ftp_size(ftpbuf_t *ftp, const char *path);
diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c
index eb2f8bc4d5..9d2673360a 100644
--- a/ext/ftp/php_ftp.c
+++ b/ext/ftp/php_ftp.c
@@ -114,7 +114,6 @@ PHP_MINFO_FUNCTION(ftp)
xtype = mode; \
}
-#define FILEP(fp, pval) ZEND_FETCH_RESOURCE(fp, FILE *, &pval, -1, "File-Handle", php_file_le_fopen());
/* {{{ proto resource ftp_connect(string host [, int port [, int timeout)]])
Opens a FTP stream */
@@ -401,7 +400,7 @@ PHP_FUNCTION(ftp_fget)
zval *z_ftp, *z_file;
ftpbuf_t *ftp;
ftptype_t xtype;
- FILE *fp;
+ php_stream *stream;
char *file;
int file_len, mode;
@@ -410,15 +409,15 @@ PHP_FUNCTION(ftp_fget)
}
ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
- FILEP(fp, z_file);
+ ZEND_FETCH_RESOURCE(stream, php_stream*, &z_file, -1, "File-Handle", php_file_le_stream());
XTYPE(xtype, mode);
- if (!ftp_get(ftp, fp, file, xtype) || ferror(fp)) {
+ if (!ftp_get(ftp, stream, file, xtype) || php_stream_error(stream)) {
php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf);
RETURN_FALSE;
}
- if (ferror(fp)) {
+ if (php_stream_error(stream)) {
php_error(E_WARNING, "%s(): error writing %s", get_active_function_name(TSRMLS_C), Z_STRVAL_P(z_file));
RETURN_FALSE;
}
@@ -456,8 +455,7 @@ PHP_FUNCTION(ftp_get)
zval *z_ftp;
ftpbuf_t *ftp;
ftptype_t xtype;
- FILE *outfp, *tmpfp;
- int ch;
+ php_stream * tmpstream, *outstream;
char *local, *remote;
int local_len, remote_len, mode;
@@ -471,42 +469,35 @@ PHP_FUNCTION(ftp_get)
/* get to temporary file, so if there is an error, no existing
* file gets clobbered
*/
- if ((tmpfp = tmpfile()) == NULL) {
- php_error(E_WARNING, "%s(): error opening tmpfile", get_active_function_name(TSRMLS_C));
+ tmpstream = php_stream_fopen_tmpfile();
+ if (tmpstream == NULL) {
RETURN_FALSE;
}
- if (!ftp_get(ftp, tmpfp, remote, xtype) || ferror(tmpfp)) {
- fclose(tmpfp);
+ if (!ftp_get(ftp, tmpstream, remote, xtype) || php_stream_error(tmpstream)) {
+ php_stream_close(tmpstream);
php_error(E_WARNING, "ftp_get: %s", ftp->inbuf);
RETURN_FALSE;
}
-#ifdef PHP_WIN32
- if ((outfp = VCWD_FOPEN(local, "wb")) == NULL) {
-#else
- if ((outfp = VCWD_FOPEN(local, "w")) == NULL) {
-#endif
- fclose(tmpfp);
+ outstream = php_stream_fopen(local, "wb", NULL TSRMLS_C);
+
+ if (outstream == NULL) {
+ php_stream_close(tmpstream);
php_error(E_WARNING, "%s(): error opening %s", get_active_function_name(TSRMLS_C), local);
RETURN_FALSE;
}
- rewind(tmpfp);
- while ((ch = getc(tmpfp)) != EOF)
- putc(ch, outfp);
-
- if (ferror(tmpfp) || ferror(outfp)) {
- fclose(tmpfp);
- fclose(outfp);
+ php_stream_rewind(tmpstream);
+ if (php_stream_copy_to_stream(tmpstream, outstream, 0) == 0) {
php_error(E_WARNING, "%s(): error writing %s", get_active_function_name(TSRMLS_C), local);
- RETURN_FALSE;
+ RETVAL_FALSE;
}
+ else
+ RETVAL_TRUE;
- fclose(tmpfp);
- fclose(outfp);
-
- RETURN_TRUE;
+ php_stream_close(tmpstream);
+ php_stream_close(outstream);
}
/* }}} */
@@ -517,8 +508,8 @@ PHP_FUNCTION(ftp_fput)
zval *z_ftp, *z_file;
ftpbuf_t *ftp;
ftptype_t xtype;
- int type, mode, remote_len;
- void *rsrc;
+ int mode, remote_len;
+ php_stream *stream;
char *remote;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsrl", &z_ftp, &remote, &remote_len, &z_file, &mode) == FAILURE) {
@@ -526,11 +517,10 @@ PHP_FUNCTION(ftp_fput)
}
ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
- rsrc = zend_fetch_resource(&z_file TSRMLS_CC, -1, "File-Handle", &type, 3, php_file_le_fopen(), php_file_le_popen(), php_file_le_socket());
- ZEND_VERIFY_RESOURCE(rsrc);
+ ZEND_FETCH_RESOURCE(stream, php_stream*, &z_file, -1, "File-Handle", php_file_le_stream());
XTYPE(xtype, mode);
- if (!ftp_put(ftp, remote, (FILE*)rsrc, *(int*) rsrc, (type==php_file_le_socket()), xtype)) {
+ if (!ftp_put(ftp, remote, stream, xtype)) {
php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf);
RETURN_FALSE;
}
@@ -546,9 +536,9 @@ PHP_FUNCTION(ftp_put)
zval *z_ftp;
ftpbuf_t *ftp;
ftptype_t xtype;
- FILE *infp;
char *remote, *local;
int remote_len, local_len, mode;
+ php_stream * instream;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssl", &z_ftp, &remote, &remote_len, &local, &local_len, &mode) == FAILURE) {
return;
@@ -557,20 +547,18 @@ PHP_FUNCTION(ftp_put)
ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
XTYPE(xtype, mode);
-#ifdef PHP_WIN32
- if ((infp = VCWD_FOPEN(local, "rb")) == NULL) {
-#else
- if ((infp = VCWD_FOPEN(local, "r")) == NULL) {
-#endif
- php_error(E_WARNING, "%s(): error opening %s", get_active_function_name(TSRMLS_C), local);
+ instream = php_stream_fopen(local, "rb", NULL TSRMLS_C);
+
+ if (instream == NULL) {
RETURN_FALSE;
}
- if (!ftp_put(ftp, remote, infp, 0, 0, xtype) || ferror(infp)) {
- fclose(infp);
+
+ if (!ftp_put(ftp, remote, instream, xtype) || php_stream_error(instream)) {
+ php_stream_close(instream);
php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf);
RETURN_FALSE;
}
- fclose(infp);
+ php_stream_close(instream);
RETURN_TRUE;
}
diff --git a/ext/gd/gd.c b/ext/gd/gd.c
index 1709c68ade..2bdeb0b6d4 100644
--- a/ext/gd/gd.c
+++ b/ext/gd/gd.c
@@ -441,8 +441,7 @@ PHP_FUNCTION(imageloadfont)
int hdr_size = sizeof(gdFont) - sizeof(char *);
int ind, body_size, n=0, b, i, body_size_check;
gdFontPtr font;
- FILE *fp;
- int issock=0, socketd=0;
+ php_stream * stream;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &file) == FAILURE) {
ZEND_WRONG_PARAM_COUNT();
@@ -450,13 +449,8 @@ PHP_FUNCTION(imageloadfont)
convert_to_string_ex(file);
-#ifdef PHP_WIN32
- fp = VCWD_FOPEN(Z_STRVAL_PP(file), "rb");
-#else
- fp = php_fopen_wrapper(Z_STRVAL_PP(file), "r", IGNORE_PATH|IGNORE_URL_WIN, &issock, &socketd, NULL TSRMLS_CC);
-#endif
- if (fp == NULL) {
- php_error(E_WARNING, "ImageFontLoad: unable to open file");
+ stream = php_stream_open_wrapper(Z_STRVAL_PP(file), "rb", IGNORE_PATH|IGNORE_URL_WIN|REPORT_ERRORS, NULL TSRMLS_CC);
+ if (stream == NULL) {
RETURN_FALSE;
}
@@ -474,22 +468,22 @@ PHP_FUNCTION(imageloadfont)
*/
font = (gdFontPtr)emalloc(sizeof(gdFont));
b = 0;
- while (b < hdr_size && (n = fread(&font[b], 1, hdr_size - b, fp)))
+ while (b < hdr_size && (n = php_stream_read(stream, (char*)&font[b], hdr_size - b)))
b += n;
if (!n) {
- fclose(fp);
+ php_stream_close(stream);
efree(font);
- if (feof(fp)) {
+ if (php_stream_eof(stream)) {
php_error(E_WARNING, "ImageFontLoad: end of file while reading header");
} else {
php_error(E_WARNING, "ImageFontLoad: error while reading header");
}
RETURN_FALSE;
}
- i = ftell(fp);
- fseek(fp, 0, SEEK_END);
- body_size_check = ftell(fp) - hdr_size;
- fseek(fp, i, SEEK_SET);
+ i = php_stream_tell(stream);
+ php_stream_seek(stream, 0, SEEK_END);
+ body_size_check = php_stream_tell(stream) - hdr_size;
+ php_stream_seek(stream, i, SEEK_SET);
body_size = font->w * font->h * font->nchars;
if (body_size != body_size_check) {
font->w = FLIPWORD(font->w);
@@ -505,20 +499,20 @@ PHP_FUNCTION(imageloadfont)
font->data = emalloc(body_size);
b = 0;
- while (b < body_size && (n = fread(&font->data[b], 1, body_size - b, fp)))
+ while (b < body_size && (n = php_stream_read(stream, &font->data[b], body_size - b)))
b += n;
if (!n) {
- fclose(fp);
+ php_stream_close(stream);
efree(font->data);
efree(font);
- if (feof(fp)) {
+ if (php_stream_eof(stream)) {
php_error(E_WARNING, "ImageFontLoad: end of file while reading body");
} else {
php_error(E_WARNING, "ImageFontLoad: error while reading body");
}
RETURN_FALSE;
}
- fclose(fp);
+ php_stream_close(stream);
/* Adding 5 to the font index so we will never have font indices
* that overlap with the old fonts (with indices 1-5). The first
@@ -1132,17 +1126,15 @@ PHP_FUNCTION(imagecreatefromstring)
}
/* }}} */
-size_t php_fread_all(char **buf, int socket, FILE *fp, int issock);
-
/* {{{ _php_image_create_from
*/
static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)())
{
zval **file, **srcx, **srcy, **width, **height;
- gdImagePtr im;
+ gdImagePtr im = NULL;
char *fn=NULL;
- FILE *fp;
- int issock=0, socketd=0;
+ php_stream * stream;
+ FILE * fp = NULL;
int argc=ZEND_NUM_ARGS();
if ((image_type == PHP_GDIMG_TYPE_GD2PART && argc != 4) ||
@@ -1158,14 +1150,8 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
fn = Z_STRVAL_PP(file);
-#ifdef PHP_WIN32
- fp = VCWD_FOPEN(fn, "rb");
-#else
- fp = php_fopen_wrapper(fn, "r", IGNORE_PATH|IGNORE_URL_WIN, &issock, &socketd, NULL TSRMLS_CC);
-#endif
- if (!fp && !socketd) {
- php_strip_url_passwd(fn);
- php_error(E_WARNING, "%s: Unable to open '%s' for reading", get_active_function_name(TSRMLS_C), fn);
+ stream = php_stream_open_wrapper(fn, "rb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL TSRMLS_CC);
+ if (stream == NULL) {
RETURN_FALSE;
}
@@ -1173,32 +1159,29 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
ioctx_func_p = NULL; /* don't allow sockets without IOCtx */
#endif
- if(issock && !ioctx_func_p) {
- php_error(E_WARNING, "%s: Sockets are not supported for image type '%s'", get_active_function_name(TSRMLS_C), tn);
- RETURN_FALSE;
+ /* try and avoid allocating a FILE* if the stream is not naturally a FILE* */
+ if (php_stream_is(stream, PHP_STREAM_IS_STDIO)) {
+ php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void**)&fp, REPORT_ERRORS);
}
-
- if(issock && socketd) {
+ else if (ioctx_func_p) {
#ifdef USE_GD_IOCTX
+ /* we can create an io context */
gdIOCtx* io_ctx;
size_t buff_size;
- char *buff, *buff_em;
+ char *buff;
- buff_size = php_fread_all(&buff_em, socketd, fp, issock);
+ /* needs to be malloc (persistent) - GD will free() it later */
+ buff_size = php_stream_read_all(stream, &buff, 1);
if(!buff_size) {
php_error(E_WARNING,"%s: Cannot read image data", get_active_function_name(TSRMLS_C));
- RETURN_FALSE;
+ goto out_err;
}
- buff = malloc(buff_size); /* Should be malloc! GD uses free */
- memcpy(buff, buff_em, buff_size);
- efree(buff_em);
-
io_ctx = gdNewDynamicCtx(buff_size, buff);
if(!io_ctx) {
php_error(E_WARNING,"%s: Cannot allocate GD IO context", get_active_function_name(TSRMLS_C));
- RETURN_FALSE;
+ goto out_err;
}
if (image_type == PHP_GDIMG_TYPE_GD2PART) {
im = (*ioctx_func_p)(io_ctx, Z_LVAL_PP(srcx), Z_LVAL_PP(srcy), Z_LVAL_PP(width), Z_LVAL_PP(height));
@@ -1206,8 +1189,15 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
im = (*ioctx_func_p)(io_ctx);
}
io_ctx->free(io_ctx);
-#endif
- } else {
+#endif
+ }
+ else {
+ /* try and force the stream to be FILE* */
+ if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO | PHP_STREAM_CAST_TRY_HARD, (void**)&fp, REPORT_ERRORS))
+ goto out_err;
+ }
+
+ if (!im && fp) {
if (image_type == PHP_GDIMG_TYPE_GD2PART) {
im = (*func_p)(fp, Z_LVAL_PP(srcx), Z_LVAL_PP(srcy), Z_LVAL_PP(width), Z_LVAL_PP(height));
} else {
@@ -1215,15 +1205,18 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
}
fflush(fp);
- fclose(fp);
}
- if (!im) {
- php_error(E_WARNING,"%s: '%s' is not a valid %s file", get_active_function_name(TSRMLS_C), fn, tn);
- RETURN_FALSE;
+ if (im) {
+ ZEND_REGISTER_RESOURCE(return_value, im, le_gd);
+ return;
}
- ZEND_REGISTER_RESOURCE(return_value, im, le_gd);
+ php_error(E_WARNING,"%s: '%s' is not a valid %s file", get_active_function_name(TSRMLS_C), fn, tn);
+out_err:
+ php_stream_close(stream);
+ RETURN_FALSE;
+
}
/* }}} */
diff --git a/ext/hyperwave/hw.c b/ext/hyperwave/hw.c
index 4720763893..cc2991dab8 100644
--- a/ext/hyperwave/hw.c
+++ b/ext/hyperwave/hw.c
@@ -38,9 +38,6 @@
#else
#include "build-defs.h"
#endif
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#endif
#if HYPERWAVE
@@ -2861,7 +2858,6 @@ PHP_FUNCTION(hw_new_document)
}
/* }}} */
-#define BUFSIZE 8192
/* {{{ proto hwdoc hw_new_document_from_file(string objrec, string filename)
Create a new document from a file */
PHP_FUNCTION(hw_new_document_from_file)
@@ -2872,6 +2868,7 @@ PHP_FUNCTION(hw_new_document_from_file)
int issock=0;
int socketd=0;
FILE *fp;
+ php_stream * stream;
int ready=0;
int bcount=0;
int use_include_path=0;
@@ -2884,14 +2881,10 @@ PHP_FUNCTION(hw_new_document_from_file)
convert_to_string_ex(arg1);
convert_to_string_ex(arg2);
- fp = php_fopen_wrapper(Z_STRVAL_PP(arg2), "r", use_include_path|ENFORCE_SAFE_MODE, &issock, &socketd, NULL TSRMLS_CC);
- if (!fp && !socketd){
- if (issock != BAD_URL) {
- char *tmp = estrndup(Z_STRVAL_PP(arg2), Z_STRLEN_PP(arg2));
- php_strip_url_passwd(tmp);
- php_error(E_WARNING, "hw_new_document_from_file(\"%s\") - %s", tmp, strerror(errno));
- efree(tmp);
- }
+ stream = php_stream_open_wrapper(Z_STRVAL_PP(arg2), "r", use_include_path|ENFORCE_SAFE_MODE|REPORT_ERRORS,
+ NULL TSRMLS_CC);
+
+ if (stream == NULL) {
RETURN_FALSE;
}
@@ -2899,60 +2892,10 @@ PHP_FUNCTION(hw_new_document_from_file)
if(NULL == doc)
RETURN_FALSE;
-#ifdef HAVE_MMAP
- if(!issock) {
- int fd;
- struct stat sbuf;
- off_t off;
- void *p;
- size_t len;
-
- fd = fileno(fp);
- fstat(fd, &sbuf);
-
- if (sbuf.st_size > BUFSIZE) {
- off = ftell(fp);
- len = sbuf.st_size - off;
- p = mmap(0, len, PROT_READ, MAP_SHARED, fd, off);
- if (p != (void *) MAP_FAILED) {
- doc->data = malloc(len);
- if(NULL == doc->data) {
- munmap(p, len);
- free(doc);
- RETURN_FALSE;
- }
- memcpy(doc->data, p, len);
- munmap(p, len);
- bcount = len;
- doc->size = len;
- ready = 1;
- }
- }
- }
-#endif
-
- if(!ready) {
- int b;
-
- doc->data = malloc(BUFSIZE);
- if(NULL == doc->data) {
- free(doc);
- RETURN_FALSE;
- }
- ptr = doc->data;
- while ((b = FP_FREAD(&ptr[bcount], BUFSIZE, socketd, fp, issock)) > 0) {
- bcount += b;
- doc->data = realloc(doc->data, bcount+BUFSIZE);
- ptr = doc->data;
- }
- }
-
- if (issock) {
- SOCK_FCLOSE(socketd);
- } else {
- fclose(fp);
- }
+ doc->size = php_stream_read_all(stream, &doc->data, 1);
+ php_stream_close(stream);
+
doc->data = realloc(doc->data, bcount+1);
ptr = doc->data;
ptr[bcount] = '\0';
@@ -2963,7 +2906,6 @@ PHP_FUNCTION(hw_new_document_from_file)
Z_TYPE_P(return_value) = IS_LONG;
}
/* }}} */
-#undef BUFSIZE
/* {{{ proto void hw_free_document(hwdoc doc)
Frees memory of document */
diff --git a/ext/interbase/interbase.c b/ext/interbase/interbase.c
index 86dce7501f..22b2baf7ba 100644
--- a/ext/interbase/interbase.c
+++ b/ext/interbase/interbase.c
@@ -2867,13 +2867,12 @@ PHP_FUNCTION(ibase_blob_import)
zval **link_arg, **file_arg;
int trans_n = 0, link_id = 0, trans_id = 0, size;
unsigned short b;
- int issock=0, socketd=0;
ibase_blob_handle ib_blob;
ibase_db_link *ib_link;
char bl_data[IBASE_BLOB_SEG]; /* FIXME? blob_seg_size parameter? */
- FILE *fp;
void * what;
int type;
+ php_stream * stream;
RESET_ERRMSG;
@@ -2901,11 +2900,8 @@ PHP_FUNCTION(ibase_blob_import)
RETURN_FALSE;
}
- what = zend_fetch_resource(file_arg TSRMLS_CC, -1, "File-Handle", &type, 2, php_file_le_fopen(), php_file_le_stream());
- ZEND_VERIFY_RESOURCE(what);
-
- if (type == php_file_le_fopen())
- fp = (FILE*)what;
+ stream = (php_stream*)zend_fetch_resource(file_arg TSRMLS_CC, -1, "File-Handle", &type, 1, php_file_le_stream());
+ ZEND_VERIFY_RESOURCE(stream);
ib_blob.link = ib_link->link;
ib_blob.trans_handle = ib_link->trans[trans_n];
@@ -2920,32 +2916,15 @@ PHP_FUNCTION(ibase_blob_import)
size = 0;
-#if HAVE_PHP_STREAM
- if (type == php_file_le_stream()) {
- while(b = php_stream_read((php_stream*)what, bl_data, 1, sizeof(bl_data)) > 0) {
- if (isc_put_segment(IB_STATUS, &ib_blob.bl_handle, b, bl_data)) {
- _php_ibase_error();
- RETURN_FALSE;
- }
- size += b;
-
- }
- }
- else {
-#endif
- /* Can't see much use for the issock stuff here, it should be nuked --Wez */
- while (issock?(b=SOCK_FREAD(bl_data, sizeof(bl_data), socketd)):(b = fread(bl_data, 1, sizeof(bl_data), fp)) > 0) {
+ while(b = php_stream_read((php_stream*)what, bl_data, 1, sizeof(bl_data)) > 0) {
if (isc_put_segment(IB_STATUS, &ib_blob.bl_handle, b, bl_data)) {
_php_ibase_error();
RETURN_FALSE;
}
size += b;
+
}
-#if HAVE_PHP_STREAM
- }
-#endif
-
if (isc_close_blob(IB_STATUS, &ib_blob.bl_handle)) {
_php_ibase_error();
RETURN_FALSE;
diff --git a/ext/mailparse/mailparse.c b/ext/mailparse/mailparse.c
index 6fed12f1de..d3cb046951 100755
--- a/ext/mailparse/mailparse.c
+++ b/ext/mailparse/mailparse.c
@@ -149,12 +149,12 @@ static void mailparse_rfc822t_errfunc(const char * msg, int num)
}
#define UUDEC(c) (char)(((c)-' ')&077)
-#define UU_NEXT(v) v = fgetc(infp); if (v == EOF) break; v = UUDEC(v)
-static void mailparse_do_uudecode(FILE * infp, FILE * outfp)
+#define UU_NEXT(v) v = php_stream_getc(instream); if (v == EOF) break; v = UUDEC(v)
+static void mailparse_do_uudecode(php_stream * instream, php_stream * outstream)
{
int A, B, C, D, n;
- while(!feof(infp)) {
+ while(!php_stream_eof(instream)) {
UU_NEXT(n);
while(n != 0) {
@@ -164,14 +164,14 @@ static void mailparse_do_uudecode(FILE * infp, FILE * outfp)
UU_NEXT(D);
if (n-- > 0)
- fputc( (A << 2) | (B >> 4), outfp);
+ php_stream_putc(outstream, (A << 2) | (B >> 4));
if (n-- > 0)
- fputc( (B << 4) | (C >> 2), outfp);
+ php_stream_putc(outstream, (B << 4) | (C >> 2));
if (n-- > 0)
- fputc( (C << 6) | D, outfp);
+ php_stream_putc(outstream, (C << 6) | D);
}
/* skip newline */
- fgetc(infp);
+ php_stream_getc(instream);
}
}
@@ -181,28 +181,28 @@ static void mailparse_do_uudecode(FILE * infp, FILE * outfp)
PHP_FUNCTION(mailparse_uudecode_all)
{
zval * file, * item;
- FILE *infp, *outfp=NULL, *partfp=NULL;
int type;
char * buffer = NULL;
char * outpath = NULL;
int nparts = 0;
+ php_stream * instream, *outstream = NULL, *partstream = NULL;
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());
- ZEND_VERIFY_RESOURCE(infp);
+ instream = (php_stream*)zend_fetch_resource(&file TSRMLS_CC, -1, "File-Handle", &type, 1, php_file_le_stream());
+ ZEND_VERIFY_RESOURCE(instream);
- outfp = php_open_temporary_file(NULL, "mailparse", &outpath TSRMLS_CC);
- if (outfp == NULL) {
+ outstream = php_stream_fopen_temporary_file(NULL, "mailparse", &outpath TSRMLS_CC);
+ if (outstream == NULL) {
zend_error(E_WARNING, "%s(): unable to open temp file", get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
- rewind(infp);
+ php_stream_rewind(instream);
buffer = emalloc(4096);
- while(fgets(buffer, 4096, infp)) {
+ while(php_stream_gets(instream, buffer, 4096)) {
/* Look for the "begin " sequence that identifies a uuencoded file */
if (strncmp(buffer, "begin ", 6) == 0) {
char * origfilename;
@@ -232,24 +232,24 @@ PHP_FUNCTION(mailparse_uudecode_all)
add_assoc_string(item, "origfilename", origfilename, 1);
/* create a temp file for the data */
- partfp = php_open_temporary_file(NULL, "mailparse", &outpath TSRMLS_CC);
- if (partfp) {
+ partstream = php_stream_fopen_temporary_file(NULL, "mailparse", &outpath TSRMLS_CC);
+ if (partstream) {
nparts++;
add_assoc_string(item, "filename", outpath, 0);
add_next_index_zval(return_value, item);
/* decode it */
- mailparse_do_uudecode(infp, partfp);
- fclose(partfp);
+ mailparse_do_uudecode(instream, partstream);
+ php_stream_close(partstream);
}
}
else {
/* write to the output file */
- fputs(buffer, outfp);
+ php_stream_puts(outstream, buffer);
}
}
- fclose(outfp);
- rewind(infp);
+ php_stream_close(outstream);
+ php_stream_rewind(instream);
efree(buffer);
if (nparts == 0) {
@@ -317,7 +317,6 @@ PHP_FUNCTION(mailparse_rfc822_parse_addresses)
PHP_FUNCTION(mailparse_determine_best_xfer_encoding)
{
zval ** file;
- FILE * fp;
int longline = 0;
int linelen = 0;
int c;
@@ -330,10 +329,9 @@ PHP_FUNCTION(mailparse_determine_best_xfer_encoding)
WRONG_PARAM_COUNT;
}
- what = zend_fetch_resource(file TSRMLS_CC, -1, "File-Handle", &type, 2, php_file_le_fopen(), php_file_le_stream());
+ what = zend_fetch_resource(file TSRMLS_CC, -1, "File-Handle", &type, 1, php_file_le_stream());
ZEND_VERIFY_RESOURCE(what);
-#if HAVE_PHP_STREAM
if (type == php_file_le_stream()) {
php_stream * stream = (php_stream*)what;
@@ -358,33 +356,6 @@ PHP_FUNCTION(mailparse_determine_best_xfer_encoding)
bestenc = mbfl_no_encoding_qprint;
php_stream_rewind(stream);
}
- else {
-#endif
- fp = (FILE*)what;
-
- rewind(fp);
- while(!feof(fp)) {
- c = fgetc(fp);
- if (c == EOF)
- break;
- if (c > 0x80)
- bestenc = mbfl_no_encoding_8bit;
- else if (c == 0) {
- bestenc = mbfl_no_encoding_base64;
- longline = 0;
- break;
- }
- if (c == '\n')
- linelen = 0;
- else if (++linelen > 200)
- longline = 1;
- }
- if (longline)
- bestenc = mbfl_no_encoding_qprint;
- rewind(fp);
-#if HAVE_PHP_STREAM
- }
-#endif
name = (char *)mbfl_no2preferred_mime_name(bestenc);
if (name)
@@ -401,25 +372,28 @@ PHP_FUNCTION(mailparse_determine_best_xfer_encoding)
/* {{{ proto boolean mailparse_stream_encode(resource sourcefp, resource destfp, string encoding)
Streams data from source file pointer, apply encoding and write to destfp */
-static int mailparse_fp_output(int c, void * fp)
+static int mailparse_stream_output(int c, void * stream)
{
- return fputc(c, (FILE*)fp);
+ char buf = c;
+ return php_stream_write((php_stream*)stream, &buf, 1);
}
-static int mailparse_fp_flush(void * fp)
+static int mailparse_stream_flush(void * stream)
{
- return fflush((FILE*)fp);
+ return php_stream_flush((php_stream*)stream);
}
PHP_FUNCTION(mailparse_stream_encode)
{
zval ** srcfile, ** destfile, ** encod;
- FILE * srcfp, * destfp;
+ void * what;
+ int type;
+ php_stream * srcstream, * deststream;
char * buf;
size_t len;
size_t bufsize = 2048;
enum mbfl_no_encoding enc;
mbfl_convert_filter * conv = NULL;
-
+
if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &srcfile, &destfile, &encod) == FAILURE) {
WRONG_PARAM_COUNT;
}
@@ -427,12 +401,18 @@ PHP_FUNCTION(mailparse_stream_encode)
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, 1, php_file_le_stream());
+ ZEND_VERIFY_RESOURCE(what);
+
+ srcstream = (php_stream*)what;
+
+ what = zend_fetch_resource(destfile TSRMLS_CC, -1, "File-Handle", &type, 1, php_file_le_stream());
+ ZEND_VERIFY_RESOURCE(what);
+ deststream = (php_stream*)what;
convert_to_string_ex(encod);
enc = mbfl_name2no_encoding(Z_STRVAL_PP(encod));
@@ -449,12 +429,13 @@ PHP_FUNCTION(mailparse_stream_encode)
conv = mbfl_convert_filter_new(mbfl_no_encoding_8bit,
enc,
- mailparse_fp_output,
- mailparse_fp_flush,
- destfp
+ mailparse_stream_output,
+ mailparse_stream_flush,
+ deststream
);
- while(!feof(srcfp)) {
- len = fread(buf, sizeof(char), bufsize, srcfp);
+
+ while(!php_stream_eof(srcstream)) {
+ len = php_stream_read(srcstream, buf, bufsize);
if (len > 0)
{
int i;
@@ -462,7 +443,7 @@ PHP_FUNCTION(mailparse_stream_encode)
mbfl_convert_filter_feed(buf[i], conv);
}
}
-
+
mbfl_convert_filter_flush(conv);
mbfl_convert_filter_delete(conv);
efree(buf);
diff --git a/ext/ming/ming.c b/ext/ming/ming.c
index 69bcb57c3a..46d0168c46 100644
--- a/ext/ming/ming.c
+++ b/ext/ming/ming.c
@@ -28,6 +28,7 @@
#include "ext/standard/info.h"
#include "ext/standard/file.h"
#include "ext/standard/fsock.h"
+#include "php_streams.h"
#if HAVE_MING
@@ -229,18 +230,18 @@ static SWFInput newSWFInput_sock(int socket)
static SWFInput getInput(zval **zfile TSRMLS_DC)
{
FILE *file;
+ void * what;
int type;
SWFInput input;
- file = (FILE *) zend_fetch_resource(zfile TSRMLS_CC, -1, "File-Handle", &type, 3, php_file_le_fopen(), php_file_le_popen(), php_file_le_socket());
+ what = zend_fetch_resource(zfile TSRMLS_CC, -1, "File-Handle", &type, 1, php_file_le_stream());
- if(type == php_file_le_socket())
- input = newSWFInput_sock(*(int *)file);
- else
- {
- input = newSWFInput_file(file);
- zend_list_addref(Z_LVAL_PP(zfile));
+ if (!php_stream_cast((php_stream*)what, PHP_STREAM_AS_STDIO_FILE, (void*)&file, REPORT_ERRORS)) {
+ return NULL;
}
+
+ input = newSWFInput_file(file);
+ zend_list_addref(Z_LVAL_PP(zfile));
zend_list_addref(zend_list_insert(input, le_swfinputp));
@@ -1577,22 +1578,22 @@ PHP_FUNCTION(swfmovie_output)
/* }}} */
/* {{{ swfmovie_saveToFile */
-void phpFileOutputMethod(byte b, void *data)
+void phpStreamOutputMethod(byte b, void * data)
{
- fwrite(&b, 1, 1, (FILE *)data);
+ php_stream_write((php_stream*)data, &b, 1);
}
PHP_FUNCTION(swfmovie_saveToFile)
{
zval **x;
SWFMovie movie = getMovie(getThis() TSRMLS_CC);
- void *what;
+ php_stream *what;
if((ZEND_NUM_ARGS() != 1) || zend_get_parameters_ex(1, &x) == FAILURE)
WRONG_PARAM_COUNT;
- ZEND_FETCH_RESOURCE(what, FILE *, x, -1,"File-Handle",php_file_le_fopen());
- RETURN_LONG(SWFMovie_output(movie, &phpFileOutputMethod, what));
+ ZEND_FETCH_RESOURCE(what, php_stream *, x, -1,"File-Handle",php_file_le_stream());
+ RETURN_LONG(SWFMovie_output(movie, &phpStreamOutputMethod, what));
}
@@ -1602,29 +1603,29 @@ PHP_FUNCTION(swfmovie_saveToFile)
PHP_FUNCTION(swfmovie_save)
{
zval **x;
- FILE *file;
long retval;
+ php_stream * stream;
if((ZEND_NUM_ARGS() != 1) || zend_get_parameters_ex(1, &x) == FAILURE)
WRONG_PARAM_COUNT;
if(Z_TYPE_PP(x) == IS_RESOURCE)
{
- ZEND_FETCH_RESOURCE(file, FILE *, x, -1,"File-Handle",php_file_le_fopen());
+ ZEND_FETCH_RESOURCE(stream, php_stream *, x, -1,"File-Handle",php_file_le_stream());
RETURN_LONG(SWFMovie_output(getMovie(getThis() TSRMLS_CC),
- &phpFileOutputMethod, file));
+ &phpStreamOutputMethod, stream));
}
convert_to_string_ex(x);
- file = VCWD_FOPEN(Z_STRVAL_PP(x), "wb");
+ stream = php_stream_open_wrapper(Z_STRVAL_PP(x), "wb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, TSRMLS_CC);
- if(file == NULL)
- php_error(E_ERROR, "couldn't open file %s for writing", Z_STRVAL_PP(x));
+ if (stream == NULL)
+ RETURN_FALSE;
retval = SWFMovie_output(getMovie(getThis() TSRMLS_CC),
- &phpFileOutputMethod, (void *)file);
+ &phpStreamOutputMethod, (void *)stream);
fclose(file);
diff --git a/ext/pdf/pdf.c b/ext/pdf/pdf.c
index 5aa6d4394c..f283f0ce87 100644
--- a/ext/pdf/pdf.c
+++ b/ext/pdf/pdf.c
@@ -36,6 +36,7 @@
#include "ext/standard/head.h"
#include "ext/standard/info.h"
#include "ext/standard/file.h"
+#include "php_streams.h"
#if HAVE_LIBGD13
#include "ext/gd/php_gd.h"
@@ -464,7 +465,9 @@ PHP_FUNCTION(pdf_set_info_keywords)
PHP_FUNCTION(pdf_open)
{
zval **file;
- FILE *fp;
+ void * what;
+ int type;
+ FILE *fp = NULL;
PDF *pdf;
int argc = ZEND_NUM_ARGS();
@@ -473,7 +476,12 @@ PHP_FUNCTION(pdf_open)
if (argc != 1 || zend_get_parameters_ex(1, &file) == FAILURE) {
fp = NULL;
} else {
- ZEND_FETCH_RESOURCE(fp, FILE *, file, -1, "File-Handle", php_file_le_fopen());
+ what = zend_fetch_resource(file TSRMLS_CC, -1, "File-Handle", &type, 1, php_file_le_stream());
+ ZEND_VERIFY_RESOURCE(what);
+
+ if (!php_stream_cast((php_stream*)what, PHP_STREAM_AS_STDIO, (void*)&fp, 1) == FAILURE) {
+ RETURN_FALSE;
+ }
/* XXX should do a zend_list_addref for <fp> here! */
}
diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
index fa96dd254c..35d31bcae5 100644
--- a/ext/pgsql/pgsql.c
+++ b/ext/pgsql/pgsql.c
@@ -1434,9 +1434,8 @@ PHP_FUNCTION(pg_trace)
int id = -1;
PGconn *pgsql;
char *mode = "w";
- int issock, socketd;
FILE *fp;
-
+ php_stream * stream;
id = PGG(default_link);
switch (ZEND_NUM_ARGS()) {
@@ -1469,15 +1468,18 @@ PHP_FUNCTION(pg_trace)
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, z_pgsql_link, id, "PostgreSQL link", le_link, le_plink);
convert_to_string_ex(z_filename);
- fp = php_fopen_wrapper(Z_STRVAL_PP(z_filename), mode, ENFORCE_SAFE_MODE, &issock, &socketd, NULL TSRMLS_CC);
+ stream = php_stream_open_wrapper(Z_STRVAL_PP(z_filename), mode, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL TSRMLS_CC);
- if (!fp) {
- php_error(E_WARNING, "Unable to open %s for logging", Z_STRVAL_PP(z_filename));
+ if (!stream) {
RETURN_FALSE;
}
-
+
+ if (!php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void**)fp, REPORT_ERRORS)) {
+ php_stream_close(stream);
+ RETURN_FALSE;
+ }
+ ZEND_REGISTER_RESOURCE(NULL, stream, php_file_le_stream());
PQtrace(pgsql, fp);
- ZEND_REGISTER_RESOURCE(NULL, fp, php_file_le_fopen());
RETURN_TRUE;
}
/* }}} */
diff --git a/ext/recode/recode.c b/ext/recode/recode.c
index fa1dcd46b8..488e3b3cfd 100644
--- a/ext/recode/recode.c
+++ b/ext/recode/recode.c
@@ -26,6 +26,7 @@
#include "php.h"
#include "php_recode.h"
+#include "php_streams.h"
#if HAVE_LIBRECODE
#include "ext/standard/info.h"
@@ -162,28 +163,38 @@ PHP_FUNCTION(recode_file)
int success;
pval **req;
pval **input, **output;
+ php_stream * instream, *outstream;
FILE *in_fp, *out_fp;
int in_type, out_type;
+
if (ZEND_NUM_ARGS() != 3
|| zend_get_parameters_ex(3, &req, &input, &output) == FAILURE) {
WRONG_PARAM_COUNT;
}
- in_fp = zend_fetch_resource(input TSRMLS_CC,-1, "File-Handle", &in_type,
- 2, php_file_le_fopen(), php_file_le_popen());
- if (!in_fp) {
+ instream = zend_fetch_resource(input TSRMLS_CC,-1, "File-Handle", &in_type,
+ 1, php_file_le_stream());
+
+ if (!instream) {
php_error(E_WARNING,"Unable to find input file identifier");
RETURN_FALSE;
}
- out_fp = zend_fetch_resource(output TSRMLS_CC,-1, "File-Handle", &out_type,
- 2, php_file_le_fopen(), php_file_le_popen());
- if (!out_fp) {
+ if (!php_stream_cast(instream, PHP_STREAM_AS_STDIO, (void**)&in_fp, REPORT_ERRORS)) {
+ RETURN_FALSE;
+ }
+
+ outstream = zend_fetch_resource(output TSRMLS_CC,-1, "File-Handle", &out_type,
+ 1, php_file_le_stream());
+ if (!outstream) {
php_error(E_WARNING,"Unable to find output file identifier");
RETURN_FALSE;
}
-
+ if (!php_stream_cast(outstream, PHP_STREAM_AS_STDIO, (void**)&out_fp, REPORT_ERRORS)) {
+ RETURN_FALSE;
+ }
+
convert_to_string_ex(req);
request = recode_new_request(ReSG(outer));
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 8033e577b8..89e354891a 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -20,6 +20,7 @@
/* $Id$ */
#include "php.h"
+#include "php_streams.h"
#include "php_main.h"
#include "php_globals.h"
#include "php_ini.h"
@@ -274,6 +275,7 @@ function_entry basic_functions[] = {
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)
@@ -621,9 +623,7 @@ function_entry basic_functions[] = {
PHP_FE(socket_set_blocking, NULL)
#if HAVE_PHP_STREAM
- PHP_FE(fopenstream, NULL)
-#else
- PHP_FALIAS(fopenstream, warn_not_available, NULL)
+ PHP_FE(fgetwrapperdata, NULL)
#endif
#if HAVE_SYS_TIME_H
@@ -1004,15 +1004,16 @@ PHP_MINIT_FUNCTION(basic)
if (PG(allow_url_fopen)) {
- if (FAILURE == php_register_url_wrapper("http", php_fopen_url_wrap_http TSRMLS_CC)) {
+ if (FAILURE == php_register_url_stream_wrapper("http", &php_stream_http_wrapper TSRMLS_CC))
return FAILURE;
- }
- if (FAILURE == php_register_url_wrapper("ftp", php_fopen_url_wrap_ftp TSRMLS_CC)) {
+ if (FAILURE == php_register_url_stream_wrapper("php", &php_stream_php_wrapper TSRMLS_CC))
return FAILURE;
- }
- if (FAILURE == php_register_url_wrapper("php", php_fopen_url_wrap_php TSRMLS_CC)) {
+ if (FAILURE == php_register_url_stream_wrapper("ftp", &php_stream_ftp_wrapper TSRMLS_CC))
return FAILURE;
- }
+# if HAVE_OPENSSL_EXT
+ if (FAILURE == php_register_url_stream_wrapper("https", &php_stream_http_wrapper TSRMLS_CC))
+ return FAILURE;
+# endif
}
return SUCCESS;
@@ -1028,9 +1029,13 @@ PHP_MSHUTDOWN_FUNCTION(basic)
#endif
if (PG(allow_url_fopen)) {
- php_unregister_url_wrapper("http" TSRMLS_CC);
- php_unregister_url_wrapper("ftp" TSRMLS_CC);
- php_unregister_url_wrapper("php" TSRMLS_CC);
+ php_unregister_url_stream_wrapper("http" TSRMLS_CC);
+ php_unregister_url_stream_wrapper("ftp" TSRMLS_CC);
+ php_unregister_url_stream_wrapper("php" TSRMLS_CC);
+# if HAVE_OPENSSL_EXT
+ php_unregister_url_stream_wrapper("https" TSRMLS_CC);
+# endif
+
}
UNREGISTER_INI_ENTRIES();
@@ -1503,8 +1508,7 @@ PHP_FUNCTION(error_log)
PHPAPI int _php_error_log(int opt_err, char *message, char *opt, char *headers TSRMLS_DC)
{
- FILE *logfile;
- int issock = 0, socketd = 0;;
+ php_stream * stream = NULL;
switch (opt_err) {
@@ -1528,13 +1532,11 @@ PHPAPI int _php_error_log(int opt_err, char *message, char *opt, char *headers T
break;
case 3: /*save to a file */
- logfile = php_fopen_wrapper(opt, "a", (IGNORE_URL | ENFORCE_SAFE_MODE), &issock, &socketd, NULL TSRMLS_CC);
- if (!logfile) {
- php_error(E_WARNING, "error_log: Unable to write to %s", opt);
+ stream = php_stream_open_wrapper(opt, "a", IGNORE_URL | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL TSRMLS_CC);
+ if (!stream)
return FAILURE;
- }
- fwrite(message, strlen(message), 1, logfile);
- fclose(logfile);
+ php_stream_write(stream, message, strlen(message));
+ php_stream_close(stream);
break;
default:
diff --git a/ext/standard/exec.c b/ext/standard/exec.c
index 321a6d94d5..34a4cfbaf8 100644
--- a/ext/standard/exec.c
+++ b/ext/standard/exec.c
@@ -51,6 +51,7 @@ int php_Exec(int type, char *cmd, pval *array, pval *return_value TSRMLS_DC)
int overflow_limit, lcmd, ldir;
int rsrc_id;
char *b, *c, *d=NULL;
+ php_stream * stream = NULL;
#if PHP_SIGCHILD
void (*sig_handler)();
#endif
@@ -141,7 +142,9 @@ int php_Exec(int type, char *cmd, pval *array, pval *return_value TSRMLS_DC)
* fd gets pclosed
*/
- rsrc_id = ZEND_REGISTER_RESOURCE(NULL, fp, php_file_le_popen());
+ stream = php_stream_fopen_from_pipe(fp, "rb");
+ if (stream)
+ rsrc_id = ZEND_REGISTER_RESOURCE(NULL, stream, php_file_le_stream());
if (type != 3) {
l=0;
diff --git a/ext/standard/file.c b/ext/standard/file.c
index 6e918eb5b1..30cbf8346d 100644
--- a/ext/standard/file.c
+++ b/ext/standard/file.c
@@ -16,8 +16,8 @@
| Stig Bakken <ssb@fast.no> |
| Andi Gutmans <andi@zend.com> |
| Zeev Suraski <zeev@zend.com> |
- | PHP 4.0 patches by Thies C. Arntzen <thies@thieso.net> |
- | PHP 4.1 streams by Wez Furlong (wez@thebrainroom.com) |
+ | PHP 4.0 patches by Thies C. Arntzen (thies@thieso.net) |
+ | 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
@@ -103,79 +104,26 @@ php_file_globals file_globals;
/* {{{ ZTS-stuff / Globals / Prototypes */
/* sharing globals is *evil* */
-static int le_fopen, le_popen, le_socket;
-/* sorry folks; including this even if you haven't enabled streams
- saves a zillion ifdefs */
static int le_stream = FAILURE;
-
/* }}} */
/* {{{ Module-Stuff */
-static void _file_popen_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
-{
- FILE *pipe = (FILE *)rsrc->ptr;
-
- FG(pclose_ret) = pclose(pipe);
-}
-
-
-static void _file_socket_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
-{
- int *sock = (int *)rsrc->ptr;
-
- SOCK_FCLOSE(*sock);
-#if HAVE_SHUTDOWN
- shutdown(*sock, 0);
-#endif
- efree(sock);
-}
-
-#if HAVE_PHP_STREAM
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
PHPAPI int php_file_le_stream(void)
{
return le_stream;
}
-static void _file_fopen_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
-{
- FILE *fp = (FILE *)rsrc->ptr;
-
- fclose(fp);
-}
-
-
-PHPAPI int php_file_le_fopen(void) /* XXX doe we really want this???? */
-{
- return le_fopen;
-}
-
-PHPAPI int php_file_le_popen(void) /* XXX you may not like this, but I need it. -- KK */
-{
- return le_popen;
-}
-
-
-PHPAPI int php_file_le_socket(void) /* XXX doe we really want this???? */
-{
- return le_socket;
-}
-
-
static void file_globals_ctor(php_file_globals *file_globals_p TSRMLS_DC)
{
- zend_hash_init(&FG(ht_fsock_keys), 0, NULL, NULL, 1);
- zend_hash_init(&FG(ht_fsock_socks), 0, NULL, (void (*)(void *))php_msock_destroy, 1);
- FG(def_chunk_size) = PHP_FSOCK_CHUNK_SIZE;
- FG(phpsockbuf) = NULL;
+ zend_hash_init(&FG(ht_persistent_socks), 0, NULL, NULL, 1);
FG(fgetss_state) = 0;
FG(pclose_ret) = 0;
}
@@ -183,21 +131,13 @@ static void file_globals_ctor(php_file_globals *file_globals_p TSRMLS_DC)
static void file_globals_dtor(php_file_globals *file_globals_p TSRMLS_DC)
{
- zend_hash_destroy(&FG(ht_fsock_socks));
- zend_hash_destroy(&FG(ht_fsock_keys));
- php_cleanup_sockbuf(1 TSRMLS_CC);
+ zend_hash_destroy(&FG(ht_persistent_socks));
}
PHP_MINIT_FUNCTION(file)
{
- le_fopen = zend_register_list_destructors_ex(_file_fopen_dtor, NULL, "file", module_number);
- le_popen = zend_register_list_destructors_ex(_file_popen_dtor, NULL, "pipe", module_number);
- le_socket = zend_register_list_destructors_ex(_file_socket_dtor, NULL, "socket", module_number);
-
-#if HAVE_PHP_STREAM
le_stream = zend_register_list_destructors_ex(_file_stream_dtor, NULL, "stream", module_number);
-#endif
#ifdef ZTS
ts_allocate_id(&file_globals_id, sizeof(php_file_globals), (ts_allocate_ctor) file_globals_ctor, (ts_allocate_dtor) file_globals_dtor);
@@ -243,23 +183,14 @@ PHP_FUNCTION(flock)
WRONG_PARAM_COUNT;
}
- what = zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream);
+ what = zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", &type, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
-#if HAVE_PHP_STREAM
- if (type == le_stream) {
- if (php_stream_cast((php_stream*)what, PHP_STREAM_AS_FD, (void*)&fd, 1) == FAILURE) {
- RETURN_FALSE;
- }
- } else
-#endif
- if (type == le_socket) {
- fd = *(int *) what;
- } else {
- fd = fileno((FILE*) what);
+ if (php_stream_cast((php_stream*)what, PHP_STREAM_AS_FD, (void*)&fd, 1) == FAILURE) {
+ RETURN_FALSE;
}
- convert_to_long_ex(arg2);
+ convert_to_long_ex(arg2);
act = Z_LVAL_PP(arg2) & 3;
if (act < 1 || act > 3) {
@@ -307,15 +238,11 @@ PHP_FUNCTION(get_meta_tags)
return;
}
- md.fp = php_fopen_wrapper(filename, "rb",
- use_include_path | ENFORCE_SAFE_MODE, &md.issock, &md.socketd, NULL TSRMLS_CC);
- if (!md.fp && !md.socketd) {
- if (md.issock != BAD_URL) {
- char *tmp = estrndup(filename, filename_len);
- php_strip_url_passwd(tmp);
- php_error(E_WARNING, "get_meta_tags(\"%s\") - %s", tmp, strerror(errno));
- efree(tmp);
- }
+ md.stream = php_stream_open_wrapper(filename, "rb",
+ use_include_path | ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ NULL TSRMLS_CC);
+
+ if (!md.stream) {
RETURN_FALSE;
}
@@ -434,11 +361,7 @@ PHP_FUNCTION(get_meta_tags)
md.token_data = NULL;
}
- if (md.issock) {
- SOCK_FCLOSE(md.socketd);
- } else {
- fclose(md.fp);
- }
+ php_stream_close(md.stream);
}
/* }}} */
@@ -451,13 +374,12 @@ PHP_FUNCTION(file)
{
char *filename;
int filename_len;
- FILE *fp;
char *slashed, *target_buf;
register int i = 0;
- int issock = 0, socketd = 0;
int target_len, len;
zend_bool use_include_path = 0;
zend_bool reached_eof = 0;
+ php_stream * stream;
/* Parse arguments */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b",
@@ -465,15 +387,10 @@ PHP_FUNCTION(file)
return;
}
- fp = php_fopen_wrapper(filename, "rb",
- use_include_path | ENFORCE_SAFE_MODE, &issock, &socketd, NULL TSRMLS_CC);
- if (!fp && !socketd) {
- if (issock != BAD_URL) {
- char *tmp = estrndup(filename, filename_len);
- php_strip_url_passwd(tmp);
- php_error(E_WARNING, "file(\"%s\") - %s", tmp, strerror(errno));
- efree(tmp);
- }
+ stream = php_stream_open_wrapper(filename, "rb",
+ use_include_path | ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ NULL TSRMLS_CC);
+ if (!stream) {
RETURN_FALSE;
}
@@ -491,7 +408,7 @@ PHP_FUNCTION(file)
target_buf = (char *) erealloc(target_buf, target_len+PHP_FILE_BUF_SIZE+1);
target_buf[target_len+PHP_FILE_BUF_SIZE] = 0; /* avoid overflows */
}
- if (FP_FGETS(target_buf+target_len, PHP_FILE_BUF_SIZE, socketd, fp, issock)==NULL) {
+ if (php_stream_gets(stream, target_buf+target_len, PHP_FILE_BUF_SIZE)==NULL) {
if (target_len==0) {
efree(target_buf);
break;
@@ -518,11 +435,7 @@ PHP_FUNCTION(file)
target_buf = NULL;
target_len = 0;
}
- if (issock) {
- SOCK_FCLOSE(socketd);
- } else {
- fclose(fp);
- }
+ php_stream_close(stream);
}
/* }}} */
@@ -558,56 +471,54 @@ PHP_FUNCTION(tempnam)
Create a temporary file that will be deleted automatically after use */
PHP_NAMED_FUNCTION(php_if_tmpfile)
{
- FILE *fp;
+ php_stream * stream;
+
if (ZEND_NUM_ARGS() != 0) {
WRONG_PARAM_COUNT;
}
- fp = tmpfile();
- if (fp == NULL) {
- php_error(E_WARNING, "tmpfile(): %s", strerror(errno));
+ stream = php_stream_fopen_tmpfile();
+
+ if (stream) {
+ ZEND_REGISTER_RESOURCE(return_value, stream, le_stream);
+ }
+ else {
RETURN_FALSE;
}
- ZEND_REGISTER_RESOURCE(return_value, fp, le_fopen);
}
/* }}} */
-#if HAVE_PHP_STREAM
-/* {{{ proto resource fopenstream(string filename, string mode)
+/* {{{ proto resource fgetwrapperdata(resource fp)
*/
-PHP_FUNCTION(fopenstream)
+PHP_FUNCTION(fgetwrapperdata)
{
- zval ** zfilename, ** zmode;
+ zval **arg1;
php_stream * stream;
- if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &zfilename, &zmode) == FAILURE) {
+ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
WRONG_PARAM_COUNT;
}
- 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*)zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", NULL, 1, le_stream);
+ ZEND_VERIFY_RESOURCE(stream);
- 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));
- RETURN_FALSE;
+ if (stream->wrapperdata) {
+ *return_value = *(stream->wrapperdata);
+ zval_copy_ctor(return_value);
}
- ZEND_REGISTER_RESOURCE(return_value, stream, le_stream);
+ else
+ RETURN_FALSE;
+
}
/* }}} */
-#endif
/* {{{ proto resource fopen(string filename, string mode [, bool use_include_path])
Open a file or a URL and return a file pointer */
PHP_NAMED_FUNCTION(php_if_fopen)
{
zval **arg1, **arg2, **arg3;
- FILE *fp;
- char *p;
- int *sock;
int use_include_path = 0;
- int issock=0, socketd=0;
-
+ php_stream * stream;
+
switch(ZEND_NUM_ARGS()) {
case 2:
if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
@@ -626,35 +537,16 @@ PHP_NAMED_FUNCTION(php_if_fopen)
}
convert_to_string_ex(arg1);
convert_to_string_ex(arg2);
- p = estrndup(Z_STRVAL_PP(arg2), Z_STRLEN_PP(arg2));
- /*
- * We need a better way of returning error messages from
- * php_fopen_wrapper().
- */
- fp = php_fopen_wrapper(Z_STRVAL_PP(arg1), p,
- use_include_path | ENFORCE_SAFE_MODE, &issock, &socketd, NULL TSRMLS_CC);
- if (!fp && !socketd) {
- if (issock != BAD_URL) {
- char *tmp = estrndup(Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1));
- php_strip_url_passwd(tmp);
- php_error(E_WARNING, "fopen(\"%s\", \"%s\") - %s", tmp, p, strerror(errno));
- efree(tmp);
- }
- efree(p);
+ 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;
}
-
- efree(p);
FG(fgetss_state) = 0;
-
- if (issock) {
- sock = emalloc(sizeof(int));
- *sock = socketd;
- ZEND_REGISTER_RESOURCE(return_value, sock, le_socket);
- } else {
- ZEND_REGISTER_RESOURCE(return_value, fp, le_fopen);
- }
+ ZEND_REGISTER_RESOURCE(return_value, stream, le_stream);
+ return;
}
/* }}} */
@@ -670,7 +562,7 @@ PHP_FUNCTION(fclose)
WRONG_PARAM_COUNT;
}
- what = zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", &type, 3, le_fopen, le_socket, le_stream);
+ what = zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", &type, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
zend_list_delete(Z_LVAL_PP(arg1));
@@ -687,7 +579,8 @@ PHP_FUNCTION(popen)
FILE *fp;
char *p, *tmp = NULL;
char *b, buf[1024];
-
+ php_stream * stream;
+
if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
WRONG_PARAM_COUNT;
}
@@ -730,9 +623,16 @@ PHP_FUNCTION(popen)
RETURN_FALSE;
}
}
- efree(p);
+ stream = php_stream_fopen_from_pipe(fp, p);
+
+ if (stream == NULL) {
+ zend_error(E_WARNING, "popen(\"%s\", \"%s\"): %s", Z_STRVAL_PP(arg1), p, strerror(errno));
+ RETVAL_FALSE;
+ }
+ else
+ ZEND_REGISTER_RESOURCE(return_value, stream, le_stream);
- ZEND_REGISTER_RESOURCE(return_value, fp, le_popen);
+ efree(p);
}
/* }}} */
@@ -742,12 +642,13 @@ PHP_FUNCTION(pclose)
{
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, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
zend_list_delete(Z_LVAL_PP(arg1));
@@ -761,41 +662,25 @@ PHP_FUNCTION(feof)
{
zval **arg1;
int type;
- int issock=0;
- int socketd=0;
void *what;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
WRONG_PARAM_COUNT;
}
- what = zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream);
+ what = zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", &type, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
- if (type == le_socket) {
- issock = 1;
- socketd = *(int *) what;
- }
-
-#if HAVE_PHP_STREAM
if (type == le_stream) {
if (php_stream_eof((php_stream *) what)) {
RETURN_TRUE;
}
RETURN_FALSE;
}
- else
-#endif
- {
- if (FP_FEOF(socketd, (FILE *) what, issock)) {
- RETURN_TRUE;
- } else {
- RETURN_FALSE;
- }
- }
+ RETURN_FALSE;
}
/* }}} */
-
+/* TODO: move to main/network.c */
PHPAPI int php_set_sock_blocking(int socketd, int block)
{
int ret = SUCCESS;
@@ -839,28 +724,24 @@ PHP_FUNCTION(socket_set_blocking)
WRONG_PARAM_COUNT;
}
- what = zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", &type, 2, le_socket, le_stream);
+ what = zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", &type, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
convert_to_long_ex(arg2);
block = Z_LVAL_PP(arg2);
- if (type == le_socket) {
- socketd = *(int *) what;
- }
-#if HAVE_PHP_STREAM
- else if (type == le_stream) {
- if (php_stream_cast((php_stream *) what, PHP_STREAM_AS_SOCKETD, (void *) &socketd, 1) == FAILURE) {
- RETURN_FALSE;
- }
- }
-#endif
- if (php_set_sock_blocking(socketd, block) == FAILURE)
- RETURN_FALSE;
+ 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);
- php_sockset_blocking(socketd, block == 0 ? 0 : 1);
+ if (php_set_sock_blocking(socketd, block) == FAILURE)
+ RETURN_FALSE;
- RETURN_TRUE;
+ php_stream_sock_set_blocking((php_stream*)what, block == 0 ? 0 : 1);
+ RETURN_TRUE;
+ }
+ RETURN_FALSE;
}
/* }}} */
@@ -882,17 +763,15 @@ PHP_FUNCTION(socket_set_timeout)
zval **socket, **seconds, **microseconds;
int type;
void *what;
- int socketd = 0;
struct timeval t;
if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 3 ||
zend_get_parameters_ex(ZEND_NUM_ARGS(), &socket, &seconds, &microseconds)==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, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
- socketd = *(int *) what;
convert_to_long_ex(seconds);
t.tv_sec = Z_LVAL_PP(seconds);
@@ -905,8 +784,12 @@ PHP_FUNCTION(socket_set_timeout)
else
t.tv_usec = 0;
- php_sockset_timeout(socketd, &t);
- RETURN_TRUE;
+ if (php_stream_is((php_stream*)what, PHP_STREAM_IS_SOCKET)) {
+ php_stream_sock_set_timeout((php_stream*)what, &t);
+ RETURN_TRUE;
+ }
+
+ RETURN_FALSE;
#endif /* HAVE_SYS_TIME_H */
}
@@ -920,25 +803,30 @@ PHP_FUNCTION(socket_get_status)
zval **socket;
int type;
void *what;
- int socketd = 0;
- struct php_sockbuf *sock;
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, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
- socketd = *(int *) what;
- sock = php_get_socket(socketd);
array_init(return_value);
- add_assoc_bool(return_value, "timed_out", sock->timeout_event);
- add_assoc_bool(return_value, "blocked", sock->is_blocked);
- add_assoc_bool(return_value, "eof", sock->eof);
- add_assoc_long(return_value, "unread_bytes", sock->writepos - sock->readpos);
+ if (php_stream_is((php_stream*)what, PHP_STREAM_IS_SOCKET)) {
+
+ php_netstream_data_t * sock = PHP_NETSTREAM_DATA_FROM_STREAM((php_stream*)what);
+
+ add_assoc_bool(return_value, "timed_out", sock->timeout_event);
+ add_assoc_bool(return_value, "blocked", sock->is_blocked);
+ add_assoc_bool(return_value, "eof", sock->eof);
+ add_assoc_long(return_value, "unread_bytes", sock->writepos - sock->readpos);
+
+ }
+ else {
+ RETURN_FALSE;
+ }
+
}
/* }}} */
@@ -950,8 +838,6 @@ PHP_FUNCTION(fgets)
zval **arg1, **arg2;
int len = 1024, type;
char *buf;
- int issock=0;
- int socketd=0;
void *what;
int argc = ZEND_NUM_ARGS();
@@ -959,7 +845,7 @@ PHP_FUNCTION(fgets)
WRONG_PARAM_COUNT;
}
- what = zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream);
+ what = zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", &type, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
if (argc>1) {
@@ -972,35 +858,12 @@ PHP_FUNCTION(fgets)
RETURN_FALSE;
}
- if (type == le_socket) {
- issock = 1;
- socketd = *(int *) what;
- }
-
buf = emalloc(sizeof(char) * (len + 1));
/* needed because recv doesnt put a null at the end*/
memset(buf, 0, len+1);
-#if HAVE_PHP_STREAM
- if (type == le_stream) {
- if (php_stream_gets((php_stream *) what, buf, len) == NULL)
- goto exit_failed;
- }
- else
-#endif
- {
- if (type == le_socket) {
- issock = 1;
- socketd = *(int *) what;
- }
-#ifdef HAVE_FLUSHIO
- if (type == le_fopen) {
- fseek((FILE *) what, 0, SEEK_CUR);
- }
-#endif
- if (FP_FGETS(buf, len, socketd, (FILE *) what, issock) == NULL)
- goto exit_failed;
- }
+ if (php_stream_gets((php_stream *) what, buf, len) == NULL)
+ goto exit_failed;
if (PG(magic_quotes_runtime)) {
Z_STRVAL_P(return_value) = php_addslashes(buf, 0, &Z_STRLEN_P(return_value), 1 TSRMLS_CC);
@@ -1027,8 +890,6 @@ PHP_FUNCTION(fgetc)
zval **arg1;
int type;
char *buf;
- int issock=0;
- int socketd=0;
void *what;
int result;
@@ -1036,28 +897,12 @@ PHP_FUNCTION(fgetc)
WRONG_PARAM_COUNT;
}
- what = zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream);
+ what = zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", &type, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
- if (type == le_socket) {
- issock = 1;
- socketd = *(int *) what;
- }
-
-#ifdef HAVE_FLUSHIO
- if (type == le_fopen) {
- fseek((FILE *) what, 0, SEEK_CUR);
- }
-#endif
- buf = emalloc(sizeof(int));
+ buf = emalloc(2 * sizeof(char));
-#if HAVE_PHP_STREAM
- if (type == le_stream) {
- result = php_stream_getc((php_stream*)what);
- }
- else
-#endif
- result = FP_FGETC(socketd, (FILE *) what, issock);
+ result = php_stream_getc((php_stream*)what);
if (result == EOF) {
efree(buf);
@@ -1078,8 +923,6 @@ PHP_FUNCTION(fgetss)
zval **fd, **bytes, **allow=NULL;
int len, type;
char *buf;
- int issock=0;
- int socketd=0;
void *what;
char *allowed_tags=NULL;
int allowed_tags_len=0;
@@ -1104,14 +947,9 @@ PHP_FUNCTION(fgetss)
break;
}
- what = zend_fetch_resource(fd TSRMLS_CC, -1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream);
+ what = zend_fetch_resource(fd TSRMLS_CC, -1, "File-Handle", &type, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
- if (type == le_socket) {
- issock = 1;
- socketd = *(int *) what;
- }
-
convert_to_long_ex(bytes);
len = Z_LVAL_PP(bytes);
if (len < 0) {
@@ -1123,16 +961,7 @@ PHP_FUNCTION(fgetss)
/*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((php_stream *) what, buf, len) == NULL) {
- efree(buf);
- RETURN_FALSE;
- }
- }
- else
-#endif
- if (FP_FGETS(buf, len, socketd, (FILE *) what, issock) == NULL) {
+ if (php_stream_gets((php_stream *) what, buf, len) == NULL) {
efree(buf);
RETURN_FALSE;
}
@@ -1152,8 +981,6 @@ PHP_FUNCTION(fscanf)
zval **file_handle, **format_string;
int len, type;
char *buf;
- int issock=0;
- int socketd=0;
void *what;
zval ***args;
@@ -1172,7 +999,7 @@ PHP_FUNCTION(fscanf)
file_handle = args[0];
format_string = args[1];
- what = zend_fetch_resource(file_handle TSRMLS_CC, -1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream);
+ what = zend_fetch_resource(file_handle TSRMLS_CC, -1, "File-Handle", &type, 1, le_stream);
/*
* we can't do a ZEND_VERIFY_RESOURCE(what), otherwise we end up
@@ -1186,28 +1013,14 @@ PHP_FUNCTION(fscanf)
len = SCAN_MAX_FSCANF_BUFSIZE;
- if (type == le_socket) {
- issock = 1;
- socketd = *(int *) what;
- }
buf = emalloc(len + 1);
/* needed because recv doesnt put a null at the end*/
memset(buf, 0, len+1);
-#if HAVE_PHP_STREAM
- if (type == le_stream) {
- if (php_stream_gets((php_stream *) what, buf, len) == NULL) {
- efree(buf);
- RETURN_FALSE;
- }
- }
- else
-#endif
-
- if (FP_FGETS(buf, len, socketd, (FILE *) what, issock) == NULL) {
+ if (php_stream_gets((php_stream *) what, buf, len) == NULL) {
efree(buf);
RETURN_FALSE;
- }
+ }
convert_to_string_ex(format_string);
result = php_sscanf_internal(buf, Z_STRVAL_PP(format_string),
@@ -1229,8 +1042,6 @@ PHP_FUNCTION(fwrite)
zval **arg1, **arg2, **arg3=NULL;
int ret, type;
int num_bytes;
- int issock=0;
- int socketd=0;
void *what;
switch (ZEND_NUM_ARGS()) {
@@ -1255,37 +1066,16 @@ PHP_FUNCTION(fwrite)
break;
}
- what = zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", &type, 4, le_fopen,
- le_popen, le_socket, le_stream);
+ what = zend_fetch_resource(arg1 TSRMLS_CC, -1, "File-Handle", &type, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
- if (type == le_socket) {
- issock =1;
- socketd = *(int *) what;
- }
-
if (!arg3 && PG(magic_quotes_runtime)) {
zval_copy_ctor(*arg2);
php_stripslashes(Z_STRVAL_PP(arg2), &num_bytes TSRMLS_CC);
}
-#if HAVE_PHP_STREAM
- if (type == le_stream) {
- ret = php_stream_write((php_stream *) what, Z_STRVAL_PP(arg2), num_bytes);
- }
- else
-#endif
-
- if (issock){
- ret = SOCK_WRITEL(Z_STRVAL_PP(arg2), num_bytes, socketd);
- } else {
-#ifdef HAVE_FLUSHIO
- if (type == le_fopen) {
- fseek((FILE *) what, 0, SEEK_CUR);
- }
-#endif
- ret = fwrite(Z_STRVAL_PP(arg2), 1, num_bytes, (FILE *) what);
- }
+ ret = php_stream_write((php_stream *) what, Z_STRVAL_PP(arg2), num_bytes);
+
RETURN_LONG(ret);
}
/* }}} */
@@ -1296,43 +1086,20 @@ PHP_FUNCTION(fflush)
{
zval **arg1;
int ret, type;
- int issock=0;
- int socketd=0;
void *what;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
WRONG_PARAM_COUNT;
}
- what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 4, le_fopen, le_popen, le_socket, le_stream);
+ what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
-#if HAVE_PHP_STREAM
- if (type == le_stream) {
- ret = php_stream_flush((php_stream *) what);
- if (ret) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
- }
-#endif
-
- if (type == le_socket) {
- issock =1;
- socketd = *(int *) what;
- }
-
- if (issock){
- ret = fsync(socketd);
- } else {
- ret = fflush((FILE *) what);
- }
-
+ ret = php_stream_flush((php_stream *) what);
if (ret) {
RETURN_FALSE;
- } else {
- RETURN_TRUE;
}
+ RETURN_TRUE;
}
/* }}} */
@@ -1342,7 +1109,8 @@ PHP_FUNCTION(set_file_buffer)
{
zval **arg1, **arg2;
int ret, type, buff;
- void *what;
+ php_stream * stream;
+ FILE * fp;
switch (ZEND_NUM_ARGS()) {
case 2:
@@ -1356,19 +1124,20 @@ PHP_FUNCTION(set_file_buffer)
break;
}
- /* XXX: add stream support --Wez. */
-
- what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 2, le_fopen, le_popen);
- ZEND_VERIFY_RESOURCE(what);
-
+ stream = (php_stream*)zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 1, le_stream);
+ ZEND_VERIFY_RESOURCE(stream);
+ if (!php_stream_is(stream, PHP_STREAM_IS_STDIO) || !php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void**)&fp, REPORT_ERRORS)) {
+ RETURN_FALSE;
+ }
+
convert_to_long_ex(arg2);
buff = Z_LVAL_PP(arg2);
/* if buff is 0 then set to non-buffered */
if (buff == 0){
- ret = setvbuf((FILE *) what, NULL, _IONBF, 0);
+ ret = setvbuf(fp, NULL, _IONBF, 0);
} else {
- ret = setvbuf((FILE *) what, NULL, _IOFBF, buff);
+ ret = setvbuf(fp, NULL, _IOFBF, buff);
}
RETURN_LONG(ret);
@@ -1381,16 +1150,18 @@ PHP_FUNCTION(rewind)
{
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, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
- rewind((FILE *) what);
+ if (-1 == php_stream_rewind((php_stream*)what)) {
+ RETURN_FALSE;
+ }
RETURN_TRUE;
}
/* }}} */
@@ -1402,20 +1173,19 @@ PHP_FUNCTION(ftell)
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, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
- ret = ftell((FILE *) what);
- if (ret == -1) {
+ ret = php_stream_tell((php_stream*)what);
+ if (ret == -1) {
RETURN_FALSE;
}
-
RETURN_LONG(ret);
}
/* }}} */
@@ -1427,14 +1197,14 @@ PHP_FUNCTION(fseek)
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, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
convert_to_long_ex(arg2);
@@ -1443,7 +1213,7 @@ PHP_FUNCTION(fseek)
whence = Z_LVAL_PP(arg3);
}
- RETURN_LONG(fseek((FILE *) what, Z_LVAL_PP(arg2), whence));
+ RETURN_LONG(php_stream_seek((php_stream*)what, Z_LVAL_PP(arg2), whence));
}
/* }}} */
@@ -1508,27 +1278,27 @@ PHP_FUNCTION(rmdir)
}
/* }}} */
-/* {{{ php_passthru_fd */
-static size_t php_passthru_fd(int socketd, FILE *fp, int issock TSRMLS_DC)
+/* {{{ php_passthru_stream */
+static size_t php_passthru_stream(php_stream * stream TSRMLS_DC)
{
size_t bcount = 0;
int ready = 0;
char buf[8192];
- /* XXX: add stream support --Wez. */
+ int fd;
#ifdef HAVE_MMAP
- if (!issock) {
- int fd;
+ 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;
- fd = fileno(fp);
fstat(fd, &sbuf);
if (sbuf.st_size > sizeof(buf)) {
- off = ftell(fp);
+ 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) {
@@ -1543,16 +1313,14 @@ static size_t php_passthru_fd(int socketd, FILE *fp, int issock TSRMLS_DC)
}
}
#endif
-
if(!ready) {
int b;
- while ((b = FP_FREAD(buf, sizeof(buf), socketd, fp, issock)) > 0) {
+ while ((b = php_stream_read(stream, buf, sizeof(buf))) > 0) {
PHPWRITE(buf, b);
bcount += b;
}
}
-
return bcount;
}
/* }}} */
@@ -1562,12 +1330,10 @@ static size_t php_passthru_fd(int socketd, FILE *fp, int issock TSRMLS_DC)
PHP_FUNCTION(readfile)
{
zval **arg1, **arg2;
- FILE *fp;
int size=0;
int use_include_path=0;
- int issock=0, socketd=0;
- int rsrc_id;
-
+ php_stream * stream;
+
/* check args */
switch (ZEND_NUM_ARGS()) {
case 1:
@@ -1587,35 +1353,15 @@ PHP_FUNCTION(readfile)
}
convert_to_string_ex(arg1);
- /*
- * We need a better way of returning error messages from
- * php_fopen_wrapper().
- */
- fp = php_fopen_wrapper(Z_STRVAL_PP(arg1), "rb",
- use_include_path | ENFORCE_SAFE_MODE, &issock, &socketd, NULL TSRMLS_CC);
- if (!fp && !socketd) {
- if (issock != BAD_URL) {
- char *tmp = estrndup(Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1));
- php_strip_url_passwd(tmp);
- php_error(E_WARNING, "readfile(\"%s\") - %s", tmp, strerror(errno));
- efree(tmp);
- }
- RETURN_FALSE;
+ 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);
}
-
- if (issock) {
- int *sock = emalloc(sizeof(int));
- *sock = socketd;
- rsrc_id = ZEND_REGISTER_RESOURCE(NULL, sock, php_file_le_socket());
- } else {
- rsrc_id = ZEND_REGISTER_RESOURCE(NULL, fp, php_file_le_fopen());
- }
-
- size = php_passthru_fd(socketd, fp, issock TSRMLS_CC);
-
- zend_list_delete(rsrc_id);
-
- RETURN_LONG(size);
+ RETURN_FALSE;
}
/* }}} */
@@ -1655,27 +1401,16 @@ PHP_FUNCTION(fpassthru)
{
zval **arg1;
int size, type;
- int issock=0;
- int socketd=0;
void *what;
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", &type, 3, le_fopen, le_popen, le_socket);
+ what = zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
- if (type == le_socket) {
- issock = 1;
- socketd = *(int *) what;
- }
-
- size = php_passthru_fd(socketd, (FILE *) what, issock TSRMLS_CC);
-
- zend_list_delete(Z_LVAL_PP(arg1));
-
+ size = php_passthru_stream((php_stream*)what TSRMLS_CC);
RETURN_LONG(size);
}
/* }}} */
@@ -1756,24 +1491,26 @@ PHP_NAMED_FUNCTION(php_if_ftruncate)
short int ret;
int type;
void *what;
+ int fd;
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, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
- if (type == le_socket) {
+ convert_to_long_ex(size);
+
+ if (php_stream_is((php_stream*)what, PHP_STREAM_IS_SOCKET)) {
php_error(E_WARNING, "can't truncate sockets!");
RETURN_FALSE;
}
-
- convert_to_long_ex(size);
-
- ret = ftruncate(fileno((FILE *) what), Z_LVAL_PP(size));
- RETURN_LONG(ret + 1);
+ 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;
}
/* }}} */
@@ -1787,6 +1524,7 @@ PHP_NAMED_FUNCTION(php_if_fstat)
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 +1532,15 @@ PHP_NAMED_FUNCTION(php_if_fstat)
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, 1, le_stream);
ZEND_VERIFY_RESOURCE(what);
- if (fstat(fileno((FILE *) what), &stat_sb)) {
+ if (!php_stream_cast((php_stream*)what, PHP_STREAM_AS_FD, (void*)&fd, 1)) {
+ RETURN_FALSE;
+ }
+
+ if (fstat(fd, &stat_sb)) {
RETURN_FALSE;
}
@@ -1903,57 +1644,25 @@ PHP_FUNCTION(copy)
*/
PHPAPI int php_copy_file(char *src, char *dest TSRMLS_DC)
{
- char buffer[8192];
- int fd_s, fd_t, read_bytes;
+ php_stream * srcstream = NULL, * deststream = NULL;
int ret = FAILURE;
-#ifdef PHP_WIN32
- if ((fd_s=VCWD_OPEN(src, O_RDONLY|_O_BINARY))==-1) {
-#else
- if ((fd_s=VCWD_OPEN(src, O_RDONLY))==-1) {
-#endif
- php_error(E_WARNING, "Unable to open '%s' for reading: %s", src, strerror(errno));
- return FAILURE;
- }
-#ifdef PHP_WIN32
- if ((fd_t=VCWD_OPEN_MODE(dest, _O_WRONLY|_O_CREAT|_O_TRUNC|_O_BINARY, _S_IREAD|_S_IWRITE))==-1) {
-#else
- if ((fd_t=VCWD_CREAT(dest, 0777))==-1) {
-#endif
- php_error(E_WARNING, "Unable to create '%s': %s", dest, strerror(errno));
- close(fd_s);
- return FAILURE;
- }
+ srcstream = php_stream_open_wrapper(src, "rb",
+ ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ NULL TSRMLS_CC);
-#ifdef HAVE_MMAP
- {
- void *srcfile;
- struct stat sbuf;
+ deststream = php_stream_open_wrapper(dest, "wb",
+ ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ NULL TSRMLS_CC);
- if (fstat(fd_s, &sbuf)) {
- goto cleanup;
- }
- srcfile = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, fd_s, 0);
- if (srcfile != (void *) MAP_FAILED) {
- if (write(fd_t, srcfile, sbuf.st_size) == sbuf.st_size)
- ret = SUCCESS;
- munmap(srcfile, sbuf.st_size);
- goto cleanup;
- }
- }
-#endif
+ if (srcstream && deststream)
+ ret = php_stream_copy_to_stream(srcstream, deststream, 0) == 0 ? FAILURE : SUCCESS;
- while ((read_bytes=read(fd_s, buffer, 8192))!=-1 && read_bytes!=0) {
- if (write(fd_t, buffer, read_bytes)==-1) {
- php_error(E_WARNING, "Unable to write to '%s': %s", dest, strerror(errno));
- goto cleanup;
- }
- }
- ret = SUCCESS;
+ if (srcstream)
+ php_stream_close(srcstream);
+ if (deststream)
+ php_stream_close(deststream);
-cleanup:
- close(fd_s);
- close(fd_t);
return ret;
}
/* }}} */
@@ -1964,22 +1673,14 @@ PHP_FUNCTION(fread)
{
zval **arg1, **arg2;
int len, type;
- int issock=0;
- int socketd=0;
- void *what;
+ php_stream * stream;
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);
- ZEND_VERIFY_RESOURCE(what);
- if (type == le_socket) {
- issock = 1;
- socketd = *(int *) what;
- }
+ stream = (php_stream*)zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 1, le_stream);
+ ZEND_VERIFY_RESOURCE(stream);
convert_to_long_ex(arg2);
len = Z_LVAL_PP(arg2);
@@ -1989,19 +1690,11 @@ PHP_FUNCTION(fread)
}
Z_STRVAL_P(return_value) = emalloc(len + 1);
- /* needed because recv doesnt put a null at the end*/
+ Z_STRLEN_P(return_value) = php_stream_read(stream, Z_STRVAL_P(return_value), len);
- if (!issock) {
-#ifdef HAVE_FLUSHIO
- if (type == le_fopen) {
- fseek((FILE *) what, 0, SEEK_CUR);
- }
-#endif
- Z_STRLEN_P(return_value) = fread(Z_STRVAL_P(return_value), 1, len, (FILE *) what);
- } else {
- Z_STRLEN_P(return_value) = SOCK_FREAD(Z_STRVAL_P(return_value), len, socketd);
- }
+ /* needed because recv/read/gzread doesnt put a null at the end*/
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);
@@ -2022,9 +1715,7 @@ PHP_FUNCTION(fgetcsv)
zval **fd, **bytes, **p_delim;
int len, type;
char *buf;
- int issock=0;
- int socketd=0;
- void *what;
+ php_stream * stream;
switch(ZEND_NUM_ARGS()) {
case 2:
@@ -2051,15 +1742,9 @@ PHP_FUNCTION(fgetcsv)
/* 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);
- ZEND_VERIFY_RESOURCE(what);
-
- if (type == le_socket) {
- issock = 1;
- socketd = *(int *) what;
- }
+ stream = (php_stream*)zend_fetch_resource(fd TSRMLS_CC,-1, "File-Handle", &type, 1, le_stream);
+ ZEND_VERIFY_RESOURCE(stream);
convert_to_long_ex(bytes);
len = Z_LVAL_PP(bytes);
@@ -2069,9 +1754,10 @@ PHP_FUNCTION(fgetcsv)
}
buf = emalloc(len + 1);
- /*needed because recv doesnt set null char at end*/
+ /*needed because recv/read/gzread doesnt set null char at end*/
memset(buf, 0, len + 1);
- if (FP_FGETS(buf, len, socketd, (FILE *) what, issock) == NULL) {
+
+ if (php_stream_gets(stream, buf, len) == NULL) {
efree(buf);
RETURN_FALSE;
}
@@ -2132,7 +1818,8 @@ PHP_FUNCTION(fgetcsv)
/* read a new line from input, as at start of routine */
memset(buf, 0, len+1);
- if (FP_FGETS(buf, len, socketd, (FILE *) what, issock) == NULL) {
+
+ if (php_stream_gets(stream, buf, len) == NULL) {
efree(lineEnd);
efree(temp);
efree(buf);
@@ -2206,40 +1893,6 @@ PHP_FUNCTION(realpath)
/* }}} */
#endif
-
-/* {{{ php_fread_all
- Function reads all data from file or socket and puts it into the buffer */
-size_t php_fread_all(char **buf, int socket, FILE *fp, int issock) {
- size_t ret;
- char *ptr;
- size_t len = 0, max_len;
- int step = PHP_FSOCK_CHUNK_SIZE;
- int min_room = PHP_FSOCK_CHUNK_SIZE / 4;
-
- 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;
- if(len + min_room >= max_len) {
- *buf = erealloc(*buf, max_len + step);
- max_len += step;
- ptr = *buf + len;
- }
- }
-
- if(len) {
- *buf = erealloc(*buf, len);
- } else {
- efree(*buf);
- *buf = NULL;
- }
-
- return len;
-}
-/* }}} */
-
/* See http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.2 */
#define PHP_META_HTML401_CHARS "-_.:"
@@ -2252,8 +1905,8 @@ php_meta_tags_token php_next_meta_token(php_meta_tags_data *md)
memset((void *)buff, 0, META_DEF_BUFSIZE + 1);
- while (md->ulc || (!FP_FEOF(md->socketd, md->fp, md->issock) && (ch = FP_FGETC(md->socketd, md->fp, md->issock)))) {
- if(FP_FEOF(md->socketd, md->fp, md->issock))
+ while (md->ulc || (!php_stream_eof(md->stream) && (ch = php_stream_getc(md->stream)))) {
+ if(php_stream_eof(md->stream))
break;
if (md->ulc) {
@@ -2278,8 +1931,8 @@ php_meta_tags_token php_next_meta_token(php_meta_tags_data *md)
case '"':
compliment = ch;
md->token_len = 0;
- while (!FP_FEOF(md->socketd, md->fp, md->issock) &&
- (ch = FP_FGETC(md->socketd, md->fp, md->issock)) &&
+ while (!php_stream_eof(md->stream) &&
+ (ch = php_stream_getc(md->stream)) &&
ch != compliment && ch != '<' && ch != '>') {
buff[(md->token_len)++] = ch;
@@ -2313,8 +1966,8 @@ php_meta_tags_token php_next_meta_token(php_meta_tags_data *md)
if (isalnum(ch)) {
md->token_len = 0;
buff[(md->token_len)++] = ch;
- while (!FP_FEOF(md->socketd, md->fp, md->issock) &&
- (ch = FP_FGETC(md->socketd, md->fp, md->issock)) &&
+ while (!php_stream_eof(md->stream) &&
+ (ch = php_stream_getc(md->stream)) &&
(isalnum(ch) || strchr(PHP_META_HTML401_CHARS, ch))) {
buff[(md->token_len)++] = ch;
diff --git a/ext/standard/file.h b/ext/standard/file.h
index 070eec4a5e..eee46a9de9 100644
--- a/ext/standard/file.h
+++ b/ext/standard/file.h
@@ -69,14 +69,10 @@ PHP_FUNCTION(realpath);
PHP_NAMED_FUNCTION(php_if_ftruncate);
PHP_NAMED_FUNCTION(php_if_fstat);
-/* temporary function for testing streams */
-PHP_FUNCTION(fopenstream);
+PHP_FUNCTION(fgetwrapperdata);
PHPAPI int php_set_sock_blocking(int socketd, int block);
-PHPAPI int php_file_le_fopen(void);
PHPAPI int php_file_le_stream(void);
-PHPAPI int php_file_le_popen(void);
-PHPAPI int php_file_le_socket(void);
PHPAPI int php_copy_file(char *src, char *dest TSRMLS_DC);
#define META_DEF_BUFSIZE 8192
@@ -94,9 +90,7 @@ typedef enum _php_meta_tags_token {
} php_meta_tags_token;
typedef struct _php_meta_tags_data {
- FILE *fp;
- int socketd;
- int issock;
+ php_stream * stream;
int ulc;
int lc;
char *input_buffer;
@@ -110,10 +104,7 @@ php_meta_tags_token php_next_meta_token(php_meta_tags_data *);
typedef struct {
int fgetss_state;
int pclose_ret;
- HashTable ht_fsock_keys;
- HashTable ht_fsock_socks;
- struct php_sockbuf *phpsockbuf;
- size_t def_chunk_size;
+ HashTable ht_persistent_socks;
} php_file_globals;
#ifdef ZTS
diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c
index b1e1314800..b672e0087c 100644
--- a/ext/standard/fsock.c
+++ b/ext/standard/fsock.c
@@ -20,6 +20,8 @@
/* $Id$ */
+/* converted to PHP Streams and moved much code to main/network.c [wez] */
+
/* Synced with php 3.0 revision 1.121 1999-06-18 [ssb] */
/* Synced with php 3.0 revision 1.133 1999-07-21 [sas] */
@@ -86,29 +88,6 @@ static int fsock_globals_id;
extern int le_fp;
#endif
-#define CLOSE_SOCK(free_sock) \
- if(socketd >= 0) { \
- close(socketd); \
- } \
- if (free_sock) { \
- efree(sock); \
- } \
- if (key) { \
- efree(key); \
- }
-
-#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)
-
#ifdef PHP_WIN32
#define EWOULDBLOCK WSAEWOULDBLOCK
#else
@@ -136,628 +115,150 @@ PHPAPI int php_lookup_hostname(const char *addr, struct in_addr *in)
return 0;
}
/* }}} */
-/* {{{ php_is_persistent_sock */
-PHPAPI int php_is_persistent_sock(int sock)
-{
- char *key;
- TSRMLS_FETCH();
-
- if (zend_hash_find(&FG(ht_fsock_socks), (char *) &sock, sizeof(sock),
- (void **) &key) == SUCCESS) {
- return 1;
- }
- return 0;
-}
-/* }}} */
/* {{{ php_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 php_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
- pval **args[5];
- int *sock=emalloc(sizeof(int));
- int *sockp;
- int arg_count=ZEND_NUM_ARGS();
- int socketd = -1;
- unsigned char udp = 0;
- struct timeval timeout = { 60, 0 };
- unsigned short portno;
+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;
- char *key = NULL;
-
- if (arg_count > 5 || arg_count < 2 || zend_get_parameters_array_ex(arg_count, args)==FAILURE) {
- CLOSE_SOCK(1);
- WRONG_PARAM_COUNT;
+ 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;
}
- switch(arg_count) {
- case 5:
- convert_to_double_ex(args[4]);
- conv = (unsigned long) (Z_DVAL_PP(args[4]) * 1000000.0);
- timeout.tv_sec = conv / 1000000;
- timeout.tv_usec = conv % 1000000;
- /* fall-through */
- case 4:
- zval_dtor(*args[3]);
- ZVAL_STRING(*args[3], "", 1);
- /* fall-through */
- case 3:
- zval_dtor(*args[2]);
- ZVAL_LONG(*args[2], 0);
- break;
- }
- convert_to_string_ex(args[0]);
- convert_to_long_ex(args[1]);
- portno = (unsigned short) Z_LVAL_PP(args[1]);
-
- key = emalloc(Z_STRLEN_PP(args[0]) + 10);
- sprintf(key, "%s:%d", Z_STRVAL_PP(args[0]), portno);
-
- if (persistent && zend_hash_find(&FG(ht_fsock_keys), key, strlen(key) + 1,
- (void *) &sockp) == SUCCESS) {
- CLOSE_SOCK(0);
- *sock = *sockp;
- ZEND_REGISTER_RESOURCE(return_value, sock, php_file_le_socket());
+
+ hashkey = emalloc(host_len + 10);
+ sprintf(hashkey, "%s:%d", host, port);
+
+ if (persistent && zend_hash_find(&FG(ht_persistent_socks), hashkey, strlen(hashkey) + 1,
+ (void *) &stream) == SUCCESS)
+ {
+ efree(hashkey);
+ ZEND_REGISTER_RESOURCE(return_value, stream, php_file_le_stream());
return;
}
- if (portno) {
- struct sockaddr_in server;
+ /* prepare the timeout value for use */
+ conv = (unsigned long) (timeout * 1000000.0);
+ tv.tv_sec = conv / 1000000;
+ tv.tv_usec = conv % 1000000;
- memset(&server, 0, sizeof(server));
- if(Z_STRLEN_PP(args[0]) >= 6 && !memcmp(Z_STRVAL_PP(args[0]), "udp://", sizeof("udp://")-1)) {
- udp = 1;
- }
+ if (zerrno) {
+ zval_dtor(zerrno);
+ ZVAL_LONG(zerrno, 0);
+ }
+ if (zerrstr) {
+ zval_dtor(zerrstr);
+ ZVAL_STRING(zerrno, "", 1);
+ }
- socketd = socket(PF_INET, udp ? SOCK_DGRAM : SOCK_STREAM, 0);
- if (socketd == SOCK_ERR) {
- CLOSE_SOCK(1);
- RETURN_FALSE;
+ 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;
+ }
}
-
- server.sin_family = AF_INET;
-
- if(php_lookup_hostname(udp ? &Z_STRVAL_PP(args[0])[6] : Z_STRVAL_PP(args[0]), &server.sin_addr)) {
- CLOSE_SOCK(1);
- RETURN_FALSE;
+#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));
}
-
- server.sin_port = htons(portno);
-
- if (php_connect_nonb(socketd, (struct sockaddr *) &server, sizeof(server), &timeout) == SOCK_CONN_ERR) {
- CLOSE_SOCK(1);
-
- if (arg_count>2) {
- zval_dtor(*args[2]);
- ZVAL_LONG(*args[2], errno);
- }
- if (arg_count>3) {
- zval_dtor(*args[3]);
- ZVAL_STRING(*args[3], strerror(errno), 1);
+ 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 ?? */
}
- RETURN_FALSE;
- }
-#if defined(AF_UNIX)
- } else {
- /* Unix domain socket. s->strval is socket name. */
- struct sockaddr_un unix_addr;
- socketd = socket(PF_UNIX, SOCK_STREAM, 0);
- if (socketd == SOCK_ERR) {
- CLOSE_SOCK(1);
- RETURN_FALSE;
+ if (ssl_ret == FAILURE)
+ zend_error(E_WARNING, "%s(): failed to activate SSL mode %d", get_active_function_name(TSRMLS_C), ssl_flags);
}
+#endif
+
+ } else
+ stream = php_stream_sock_open_unix(host, persistent, &tv);
- memset(&unix_addr, 0, sizeof(unix_addr));
- unix_addr.sun_family = AF_UNIX;
- strlcpy(unix_addr.sun_path, Z_STRVAL_PP(args[0]), sizeof(unix_addr.sun_path));
+ if (stream && persistent) {
+ zend_hash_update(&FG(ht_persistent_socks), hashkey, strlen(hashkey) + 1,
+ &stream, sizeof(stream), NULL);
+ }
- if (php_connect_nonb(socketd, (struct sockaddr *) &unix_addr, sizeof(unix_addr), &timeout) == SOCK_CONN_ERR) {
- CLOSE_SOCK(1);
- if (arg_count>2) {
- zval_dtor(*args[2]);
- ZVAL_LONG(*args[2], errno);
- }
- if (arg_count>3) {
- zval_dtor(*args[3]);
- ZVAL_STRING(*args[3], strerror(errno), 1);
- }
- RETURN_FALSE;
+ 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);
}
-#endif /* AF_UNIX */
- }
- *sock = socketd;
- if (persistent) {
- zend_hash_update(&FG(ht_fsock_keys), key, strlen(key) + 1,
- sock, sizeof(*sock), NULL);
- zend_hash_update(&FG(ht_fsock_socks), (char *) sock, sizeof(*sock),
- key, strlen(key) + 1, NULL);
+ RETURN_FALSE;
}
-
- if (key)
- efree(key);
-
- ZEND_REGISTER_RESOURCE(return_value, sock, php_file_le_socket());
+
+ ZEND_REGISTER_RESOURCE(return_value, stream, php_file_le_stream());
}
+
/* }}} */
/* {{{ proto int fsockopen(string hostname, int port [, int errno [, string errstr [, float timeout]]])
Open Internet or Unix domain socket connection */
PHP_FUNCTION(fsockopen)
{
- php_fsockopen(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+ php_fsockopen_stream(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
}
/* }}} */
/* {{{ proto int pfsockopen(string hostname, int port [, int errno [, string errstr [, float timeout]]])
Open persistent Internet or Unix domain socket connection */
PHP_FUNCTION(pfsockopen)
{
- php_fsockopen(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
-}
-/* }}} */
-
-#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 == FG(phpsockbuf)) \
- FG(phpsockbuf) = sock->next; \
- pefree(sock, sock->persistent)
-
-PHPAPI void php_cleanup_sockbuf(int persistent TSRMLS_DC)
-{
- php_sockbuf *now, *next;
-
- for(now = FG(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) \
- php_sockbuf *sock; \
- TSRMLS_FETCH(); \
- sock = php_sockfind(socket TSRMLS_CC); \
- if(!sock) sock = php_sockcreate(socket TSRMLS_CC)
-
-static php_sockbuf *php_sockfind(int socket TSRMLS_DC)
-{
- php_sockbuf *buf = NULL, *tmp;
-
- for(tmp = FG(phpsockbuf); tmp; tmp = tmp->next)
- if(tmp->socket == socket) {
- buf = tmp;
- break;
- }
-
- return buf;
-}
-
-static php_sockbuf *php_sockcreate(int socket TSRMLS_DC)
-{
- php_sockbuf *sock;
- int persistent = php_is_persistent_sock(socket);
-
- sock = pecalloc(sizeof(*sock), 1, persistent);
- sock->socket = socket;
- if((sock->next = FG(phpsockbuf)))
- FG(phpsockbuf)->prev = sock;
- sock->persistent = persistent;
- sock->is_blocked = 1;
- sock->chunk_size = FG(def_chunk_size);
- sock->timeout.tv_sec = -1;
- FG(phpsockbuf) = sock;
-
- return sock;
-}
-
-PHPAPI php_sockbuf *php_get_socket(int socket)
-{
- SOCK_FIND(sock, socket);
- return sock;
-}
-
-PHPAPI size_t php_sock_set_def_chunk_size(size_t size)
-{
- size_t old;
- TSRMLS_FETCH();
-
- old = FG(def_chunk_size);
-
- if(size <= PHP_FSOCK_CHUNK_SIZE || size > 0)
- FG(def_chunk_size) = size;
-
- return old;
-}
-
-PHPAPI int php_sockdestroy(int socket)
-{
- int ret = 0;
- php_sockbuf *sock;
- TSRMLS_FETCH();
-
- sock = php_sockfind(socket TSRMLS_CC);
- if(sock) {
- ret = 1;
- SOCK_DESTROY(sock);
- }
-
- return ret;
-}
-
-#if !defined(PHP_WIN32)
-#undef closesocket
-#define closesocket close
-#endif
-
-#ifndef HAVE_SHUTDOWN
-#undef shutdown
-#define shutdown
-#endif
-
-#define SOCK_CLOSE(s) shutdown(s, 0); closesocket(s)
-
-PHPAPI int php_sock_close(int socket)
-{
- int ret = 0;
- php_sockbuf *sock;
- TSRMLS_FETCH();
-
- sock = php_sockfind(socket TSRMLS_CC);
- if(sock) {
- if(!sock->persistent) {
- SOCK_CLOSE(sock->socket);
- SOCK_DESTROY(sock);
- }
- } else {
- SOCK_CLOSE(socket);
- }
-
- return ret;
-}
-
-#define MAX_CHUNKS_PER_READ 10
-
-static void php_sockwait_for_data(php_sockbuf *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_sockread_internal(php_sockbuf *sock)
-{
- char buf[PHP_FSOCK_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_sockwait_for_data(sock);
- if (sock->timeout_event)
- return 0;
- }
-
- /* read at a maximum sock->chunk_size */
- 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,
- 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;
- }
-
- return nr_read;
-}
-
-static void php_sockread_total(php_sockbuf *sock, size_t maxread)
-{
- while(!sock->eof && TOREAD(sock) < maxread && !sock->timeout_event) {
- php_sockread_internal(sock);
- }
-}
-
-static size_t php_sockread(php_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 = php_sockread_internal(sock);
- if(nr_bytes == 0) break;
- nr_read += nr_bytes;
- }
-
- return nr_read;
-}
-
-PHPAPI int php_sockset_blocking(int socket, int mode)
-{
- int old;
- SOCK_FIND(sock, socket);
-
- old = sock->is_blocked;
-
- sock->is_blocked = mode;
-
- return old;
-}
-
-PHPAPI void php_sockset_timeout(int socket, struct timeval *timeout)
-{
- SOCK_FIND(sock, socket);
-
- sock->timeout = *timeout;
- sock->timeout_event = 0;
-}
-
-#define SOCK_FIND_AND_READ_MAX(max) \
- SOCK_FIND(sock, socket); \
- if(sock->is_blocked) php_sockread_total(sock, max); else php_sockread(sock)
-
-/* {{{ php_sock_fgets() */
-/*
- * FIXME: fgets depends on '\n' as line delimiter
- */
-static char * php_sock_fgets_internal(char * buf, size_t maxlen, php_sockbuf * sock)
-{
- 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_sockread_internal(sock);
- SEARCHCR();
- }
- } else {
- php_sockread(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;
-}
-PHPAPI char *php_sock_fgets(char *buf, size_t maxlen, int socket)
-{
- SOCK_FIND(sock, socket);
- return php_sock_fgets_internal(buf, maxlen, sock);
-}
-
-
-/* }}} */
-
-/*
- * 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
- */
-
-PHPAPI int php_sock_fgetc(int socket)
-{
- int ret = EOF;
- SOCK_FIND_AND_READ_MAX(1);
-
- if(TOREAD(sock) > 0) {
- ret = *READPTR(sock);
- sock->readpos++;
- }
-
- return ret;
-}
-
-PHPAPI int php_sock_feof(int socket)
-{
- int ret = 0;
- SOCK_FIND(sock, socket);
-
- if(!sock->is_blocked)
- php_sockread(sock);
-
- if(!TOREAD(sock) && sock->eof)
- ret = 1;
-
- 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);
+ php_fsockopen_stream(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
-
-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() */
-
-PHPAPI size_t php_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;
- }
-
- return ret;
-}
-
/* }}} */
-/* {{{ module start/shutdown functions */
-
- /* {{{ php_msock_destroy */
-PHPAPI void php_msock_destroy(int *data)
-{
- close(*data);
-}
-/* }}} */
-
-
-
+/* {{{ RSHUTDOWN_FUNCTION(fsock) */
PHP_RSHUTDOWN_FUNCTION(fsock)
{
- php_cleanup_sockbuf(0 TSRMLS_CC);
return SUCCESS;
}
/* }}} */
diff --git a/ext/standard/fsock.h b/ext/standard/fsock.h
index 13e5c5f196..fb134e97bc 100644
--- a/ext/standard/fsock.h
+++ b/ext/standard/fsock.h
@@ -27,54 +27,12 @@
#include "file.h"
-#define PHP_FSOCK_CHUNK_SIZE 8192
-
#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;
- size_t readbuflen;
- size_t readpos;
- size_t writepos;
- struct php_sockbuf *next;
- struct php_sockbuf *prev;
- char eof;
- char persistent;
- char is_blocked;
- size_t chunk_size;
- struct timeval timeout;
- char timeout_event;
-#if HAVE_PHP_STREAM
- php_stream * stream;
-#endif
-};
-
-typedef struct php_sockbuf php_sockbuf;
-
PHP_FUNCTION(fsockopen);
PHP_FUNCTION(pfsockopen);
PHPAPI int php_lookup_hostname(const char *addr, struct in_addr *in);
-PHPAPI char *php_sock_fgets(char *buf, size_t maxlen, int socket);
-PHPAPI size_t php_sock_fread(char *buf, size_t maxlen, int socket);
-PHPAPI int php_sock_feof(int socket);
-PHPAPI int php_sock_fgetc(int socket);
-PHPAPI int php_is_persistent_sock(int);
-PHPAPI int php_sockset_blocking(int socket, int mode);
-PHPAPI void php_sockset_timeout(int socket, struct timeval *timeout);
-PHPAPI int php_sockdestroy(int socket);
-PHPAPI int php_sock_close(int socket);
-PHPAPI size_t php_sock_set_def_chunk_size(size_t size);
-PHPAPI void php_msock_destroy(int *data);
-PHPAPI void php_cleanup_sockbuf(int persistent TSRMLS_DC);
-
-PHPAPI struct php_sockbuf *php_get_socket(int socket);
PHP_RSHUTDOWN_FUNCTION(fsock);
diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c
index 98552e1143..4c4b0543b1 100644
--- a/ext/standard/ftp_fopen_wrapper.c
+++ b/ext/standard/ftp_fopen_wrapper.c
@@ -66,22 +66,28 @@
#include "php_fopen_wrappers.h"
-static int php_get_ftp_result(int socketd)
+static int php_get_ftp_result(php_stream * stream)
{
char tmp_line[513];
- while (SOCK_FGETS(tmp_line, sizeof(tmp_line)-1, socketd) &&
+ while (php_stream_gets(stream, tmp_line, sizeof(tmp_line)-1) &&
!(isdigit((int) tmp_line[0]) && isdigit((int) tmp_line[1]) &&
isdigit((int) tmp_line[2]) && tmp_line[3] == ' '));
return strtol(tmp_line, NULL, 10);
}
+php_stream_wrapper php_stream_ftp_wrapper = {
+ php_stream_url_wrap_ftp,
+ NULL
+};
+
+
/* {{{ php_fopen_url_wrap_ftp
*/
-FILE *php_fopen_url_wrap_ftp(const char *path, char *mode, int options, int *issock, int *socketd, char **opened_path TSRMLS_DC)
+php_stream * php_stream_url_wrap_ftp(char * path, char * mode, int options, char ** opened_path TSRMLS_DC)
{
- FILE *fp=NULL;
+ php_stream *stream=NULL;
php_url *resource=NULL;
char tmp_line[512];
unsigned short portno;
@@ -91,126 +97,98 @@ FILE *php_fopen_url_wrap_ftp(const char *path, char *mode, int options, int *iss
char *tpath, *ttpath;
resource = php_url_parse((char *) path);
- if (resource == NULL) {
- php_error(E_WARNING, "Invalid URL specified, %s", path);
- *issock = BAD_URL;
+ if (resource == NULL || resource->path == NULL)
return NULL;
- } else if (resource->path == NULL) {
- php_error(E_WARNING, "No file-path specified");
- php_url_free(resource);
- *issock = BAD_URL;
- return NULL;
- }
+
/* use port 21 if one wasn't specified */
if (resource->port == 0)
resource->port = 21;
-
- *socketd = php_hostconnect(resource->host, resource->port, SOCK_STREAM, 0);
- if (*socketd == -1)
- goto errexit;
-#if 0
- if ((fpc = fdopen(*socketd, "r+")) == NULL) {
- php_url_free(resource);
- return NULL;
- }
-#ifdef HAVE_SETVBUF
- if ((setvbuf(fpc, NULL, _IONBF, 0)) != 0) {
- php_url_free(resource);
- fclose(fpc);
- return NULL;
- }
-#endif
-#endif
+ stream = php_stream_sock_open_host(resource->host, resource->port, SOCK_STREAM, 0, 0);
+ if (stream == NULL)
+ goto errexit;
+
/* Start talking to ftp server */
- result = php_get_ftp_result(*socketd);
+ result = php_get_ftp_result(stream);
if (result > 299 || result < 200)
goto errexit;
/* send the user name */
- SOCK_WRITE("USER ", *socketd);
+ php_stream_write_string(stream, "USER ");
if (resource->user != NULL) {
php_raw_url_decode(resource->user, strlen(resource->user));
- SOCK_WRITE(resource->user, *socketd);
+ php_stream_write_string(stream, resource->user);
} else {
- SOCK_WRITE("anonymous", *socketd);
+ php_stream_write_string(stream, "anonymous");
}
- SOCK_WRITE("\r\n", *socketd);
+ php_stream_write_string(stream, "\r\n");
/* get the response */
- result = php_get_ftp_result(*socketd);
+ result = php_get_ftp_result(stream);
/* if a password is required, send it */
if (result >= 300 && result <= 399) {
- SOCK_WRITE("PASS ", *socketd);
+ php_stream_write_string(stream, "PASS ");
if (resource->pass != NULL) {
php_raw_url_decode(resource->pass, strlen(resource->pass));
- SOCK_WRITE(resource->pass, *socketd);
+ php_stream_write_string(stream, resource->pass);
} else {
/* if the user has configured who they are,
send that as the password */
if (cfg_get_string("from", &scratch) == SUCCESS) {
- SOCK_WRITE(scratch, *socketd);
+ php_stream_write_string(stream, scratch);
} else {
- SOCK_WRITE("anonymous", *socketd);
+ php_stream_write_string(stream, "anonymous");
}
}
- SOCK_WRITE("\r\n", *socketd);
+ php_stream_write_string(stream, "\r\n");
/* read the response */
- result = php_get_ftp_result(*socketd);
+ result = php_get_ftp_result(stream);
}
if (result > 299 || result < 200)
goto errexit;
/* set the connection to be binary */
- SOCK_WRITE("TYPE I\r\n", *socketd);
- result = php_get_ftp_result(*socketd);
+ php_stream_write_string(stream, "TYPE I\r\n");
+ result = php_get_ftp_result(stream);
if (result > 299 || result < 200)
goto errexit;
/* find out the size of the file (verifying it exists) */
- SOCK_WRITE("SIZE ", *socketd);
- SOCK_WRITE(resource->path, *socketd);
- SOCK_WRITE("\r\n", *socketd);
+ php_stream_write_string(stream, "SIZE ");
+ php_stream_write_string(stream, resource->path);
+ php_stream_write_string(stream, "\r\n");
/* read the response */
- result = php_get_ftp_result(*socketd);
+ result = php_get_ftp_result(stream);
if (mode[0] == 'r') {
/* when reading file, it must exist */
if (result > 299 || result < 200) {
- php_error(E_WARNING, "File not found");
- php_url_free(resource);
- SOCK_FCLOSE(*socketd);
- *socketd = 0;
errno = ENOENT;
- return NULL;
+ goto errexit;
}
} else {
/* when writing file, it must NOT exist */
if (result <= 299 && result >= 200) {
- php_error(E_WARNING, "File already exists");
- php_url_free(resource);
- SOCK_FCLOSE(*socketd);
- *socketd = 0;
errno = EEXIST;
- return NULL;
+ goto errexit;
}
}
/* set up the passive connection */
/* We try EPSV first, needed for IPv6 and works on some IPv4 servers */
- SOCK_WRITE("EPSV\r\n", *socketd);
- while (SOCK_FGETS(tmp_line, sizeof(tmp_line)-1, *socketd) &&
+ php_stream_write_string(stream, "EPSV\r\n");
+ while (php_stream_gets(stream, tmp_line, sizeof(tmp_line)-1) &&
!(isdigit((int) tmp_line[0]) && isdigit((int) tmp_line[1]) &&
isdigit((int) tmp_line[2]) && tmp_line[3] == ' '));
/* check if we got a 229 response */
if (strncmp(tmp_line, "229", 3)) {
/* EPSV failed, let's try PASV */
- SOCK_WRITE("PASV\r\n", *socketd);
- while (SOCK_FGETS(tmp_line, sizeof(tmp_line)-1, *socketd) &&
+ php_stream_write_string(stream, "PASV\r\n");
+ while (php_stream_gets(stream, tmp_line, sizeof(tmp_line)-1) &&
!(isdigit((int) tmp_line[0]) && isdigit((int) tmp_line[1]) &&
isdigit((int) tmp_line[2]) && tmp_line[3] == ' '));
/* make sure we got a 227 response */
@@ -263,53 +241,33 @@ FILE *php_fopen_url_wrap_ftp(const char *path, char *mode, int options, int *iss
if (mode[0] == 'r') {
/* retrieve file */
- SOCK_WRITE("RETR ", *socketd);
+ php_stream_write_string(stream, "RETR ");
} else {
/* store file */
- SOCK_WRITE("STOR ", *socketd);
+ php_stream_write_string(stream, "STOR ");
}
if (resource->path != NULL) {
- SOCK_WRITE(resource->path, *socketd);
+ php_stream_write_string(stream, resource->path);
} else {
- SOCK_WRITE("/", *socketd);
+ php_stream_write_string(stream, "/");
}
/* close control connection */
- SOCK_WRITE("\r\nQUIT\r\n", *socketd);
- SOCK_FCLOSE(*socketd);
+ php_stream_write_string(stream, "\r\nQUIT\r\n");
+ php_stream_close(stream);
/* open the data channel */
- *socketd = php_hostconnect(resource->host, portno, SOCK_STREAM, 0);
- if (*socketd == -1)
+ stream = php_stream_sock_open_host(resource->host, portno, SOCK_STREAM, 0, 0);
+ if (stream == NULL)
goto errexit;
-#if 0
- if (mode[0] == 'r') {
- if ((fp = fdopen(*socketd, "r+")) == NULL) {
- php_url_free(resource);
- return NULL;
- }
- } else {
- if ((fp = fdopen(*socketd, "w+")) == NULL) {
- php_url_free(resource);
- return NULL;
- }
- }
-#ifdef HAVE_SETVBUF
- if ((setvbuf(fp, NULL, _IONBF, 0)) != 0) {
- php_url_free(resource);
- fclose(fp);
- return NULL;
- }
-#endif
-#endif
+
php_url_free(resource);
- *issock = 1;
- return (fp);
+ return stream;
errexit:
php_url_free(resource);
- SOCK_FCLOSE(*socketd);
- *socketd = 0;
+ if (stream)
+ php_stream_close(stream);
return NULL;
}
/* }}} */
diff --git a/ext/standard/html.c b/ext/standard/html.c
index cc2999ace1..7cf5a25de3 100644
--- a/ext/standard/html.c
+++ b/ext/standard/html.c
@@ -23,7 +23,7 @@
#include "php.h"
#include "reg.h"
#include "html.h"
-
+#include "php_string.h"
#if HAVE_LOCALE_H
#include <locale.h>
#endif
@@ -123,6 +123,21 @@ static const struct {
{ NULL }
};
+static const struct {
+ unsigned short charcode;
+ char * entity;
+ int entitylen;
+ int flags;
+} basic_entities[] = {
+ { '&', "&amp;", 5, 0 },
+ { '"', "&quot;", 6, ENT_HTML_QUOTE_DOUBLE },
+ { '\'', "&#039;", 6, ENT_HTML_QUOTE_SINGLE },
+ { '<', "&lt;", 4, 0 },
+ { '>', "&gt;", 4, 0 },
+ { 0, NULL, 0, 0 }
+};
+
+
/* {{{ get_next_char
*/
inline static unsigned short get_next_char(enum entity_charset charset,
@@ -389,19 +404,88 @@ static enum entity_charset determine_charset(char * charset_hint)
}
/* }}} */
+/* {{{ 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,17 +493,16 @@ PHPAPI char *php_escape_html_entities(unsigned char *old, int oldlen, int *newle
int mbseqlen;
unsigned char mbsequence[16]; /* allow up to 15 characters in a multibyte sequence */
unsigned short this_char = get_next_char(charset, old, &i, mbsequence, &mbseqlen);
-
+
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;
-
+
for (j=0; entity_map[j].charset != cs_terminator; j++) {
if (entity_map[j].charset == charset
@@ -432,48 +515,49 @@ PHPAPI char *php_escape_html_entities(unsigned char *old, int oldlen, int *newle
* just output the character itself */
break;
}
-
+
matches_map = 1;
break;
}
}
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, "&amp;", 5);
- len += 5;
- } else if (34 == this_char && !(quote_style&ENT_NOQUOTES)) {
- memcpy (new + len, "&quot;", 6);
- len += 6;
- } else if (39 == this_char && (quote_style&ENT_QUOTES)) {
- memcpy (new + len, "&#039;", 6);
- len += 6;
- } else if (60 == this_char) {
- memcpy (new + len, "&lt;", 4);
- len += 4;
- } else if (62 == this_char) {
- memcpy (new + len, "&gt;", 4);
- len += 4;
- } else if (this_char > 0xff) {
- /* a wide char without a named entity; pass through the original sequence */
- memcpy(new + len, mbsequence, mbseqlen);
- len += mbseqlen;
- } else {
- new [len++] = (unsigned char)this_char;
+ 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(replaced + len, mbsequence, mbseqlen);
+ len += mbseqlen;
+
+ } else
+ replaced [len++] = (unsigned char)this_char;
}
}
}
- new [len] = '\0';
+ replaced [len] = '\0';
*newlen = len;
- return new;
+ return replaced;
}
@@ -485,15 +569,15 @@ static void php_html_entities(INTERNAL_FUNCTION_PARAMETERS, int all)
{
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,
&quote_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);
}
/* }}} */
@@ -520,6 +604,25 @@ PHP_FUNCTION(htmlspecialchars)
}
/* }}} */
+/* {{{ 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,
+ &quote_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)
@@ -566,15 +669,14 @@ PHP_FUNCTION(get_html_translation_table)
/* break thru */
case HTML_SPECIALCHARS:
- ind[0]=38; add_assoc_string(return_value, ind, "&amp;", 1);
- if(quote_style&ENT_QUOTES) {
- ind[0]=39; add_assoc_string(return_value, ind, "&#039;", 1);
- }
- if(!(quote_style&ENT_NOQUOTES)) {
- ind[0]=34; add_assoc_string(return_value, ind, "&quot;", 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, "&lt;", 1);
- ind[0]=62; add_assoc_string(return_value, ind, "&gt;", 1);
break;
}
}
diff --git a/ext/standard/html.h b/ext/standard/html.h
index ac11acb0f1..5f122cbc6e 100644
--- a/ext/standard/html.h
+++ b/ext/standard/html.h
@@ -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);
diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
index 24e546bb60..41ee9d7d54 100644
--- a/ext/standard/http_fopen_wrapper.c
+++ b/ext/standard/http_fopen_wrapper.c
@@ -15,12 +15,14 @@
| Authors: Rasmus Lerdorf <rasmus@php.net> |
| Jim Winstead <jimw@php.net> |
| Hartmut Holzgraefe <hholzgra@php.net> |
+ | Wez Furlong <wez@thebrainroom.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#include "php.h"
#include "php_globals.h"
+#include "php_streams.h"
#include "php_network.h"
#include <stdio.h>
@@ -66,7 +68,256 @@
#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;
+ char tmp_line[128];
+
+ 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 */
+
+ 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 *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 (stream->wrapperdata) {
+ 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_P(stream->wrapperdata));
+ while (zend_hash_get_current_data(Z_ARRVAL_P(stream->wrapperdata), (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_P(stream->wrapperdata));
+ }
+ zval_dtor(stream->wrapperdata);
+ FREE_ZVAL(stream->wrapperdata);
+ }
+ }
+ else if (options & REPORT_ERRORS)
+ zend_error(E_WARNING, "HTTP request failed! %s", tmp_line);
+ }
+out:
+ if (http_header_line)
+ efree(http_header_line);
+ if (scratch)
+ efree(scratch);
+ php_url_free(resource);
+
+ if (stream)
+ stream->wrapperdata = response_header;
+
+ if (response_header) {
+ zval * sym;
+ MAKE_STD_ZVAL(sym);
+ *sym = *response_header;
+ zval_copy_ctor(sym);
+ ZEND_SET_SYMBOL(EG(active_symbol_table), "http_response_header", sym);
+ }
+
+
+ return stream;
+}
+
+php_stream_wrapper php_stream_http_wrapper = {
+ php_stream_url_wrap_http,
+ NULL
+};
+
+#else
+
+
/* {{{ php_fopen_url_wrap_http
*/
@@ -322,6 +573,8 @@ FILE *php_fopen_url_wrap_http(const char *path, char *mode, int options, int *is
}
/* }}} */
+#endif
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/standard/image.c b/ext/standard/image.c
index e0a93f4a97..8505078dfc 100644
--- a/ext/standard/image.c
+++ b/ext/standard/image.c
@@ -73,7 +73,7 @@ struct gfxinfo {
/* {{{ php_handle_gif
* routine to handle GIF files. If only everything were that easy... ;} */
-static struct gfxinfo *php_handle_gif (int socketd, FILE *fp, int issock)
+static struct gfxinfo *php_handle_gif (php_stream * stream)
{
struct gfxinfo *result = NULL;
unsigned char a[2];
@@ -81,12 +81,12 @@ static struct gfxinfo *php_handle_gif (int socketd, FILE *fp, int issock)
result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
- FP_FREAD(temp, 3, socketd, fp, issock); /* fseek(fp, 6L, SEEK_SET); */
+ php_stream_read(stream, temp, sizeof(temp)); /* fseek(fp, 6L, SEEK_SET); */
- FP_FREAD(a, sizeof(a), socketd, fp, issock); /* fread(a, sizeof(a), 1, fp); */
+ php_stream_read(stream, a, sizeof(a)); /* fread(a, sizeof(a), 1, fp); */
result->width = (unsigned short)a[0] | (((unsigned short)a[1])<<8);
- FP_FREAD(a, sizeof(a), socketd, fp, issock); /* fread(a, sizeof(a), 1, fp); */
+ php_stream_read(stream, a, sizeof(a)); /* fread(a, sizeof(a), 1, fp); */
result->height = (unsigned short)a[0] | (((unsigned short)a[1])<<8);
return result;
@@ -95,7 +95,7 @@ static struct gfxinfo *php_handle_gif (int socketd, FILE *fp, int issock)
/* {{{ php_handle_psd
*/
-static struct gfxinfo *php_handle_psd (int socketd, FILE *fp, int issock)
+static struct gfxinfo *php_handle_psd (php_stream * stream)
{
struct gfxinfo *result = NULL;
unsigned char a[8];
@@ -103,9 +103,9 @@ static struct gfxinfo *php_handle_psd (int socketd, FILE *fp, int issock)
unsigned long in_width, in_height;
result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
- FP_FREAD(temp, sizeof(temp), socketd, fp, issock);
+ php_stream_read(stream, temp, sizeof(temp));
- if((FP_FREAD(a, sizeof(a), socketd, fp, issock)) <= 0) {
+ if((php_stream_read(stream, a, sizeof(a))) <= 0) {
in_height = 0;
in_width = 0;
} else {
@@ -122,7 +122,7 @@ static struct gfxinfo *php_handle_psd (int socketd, FILE *fp, int issock)
/* {{{ php_handle_bmp
*/
-static struct gfxinfo *php_handle_bmp (int socketd, FILE *fp, int issock)
+static struct gfxinfo *php_handle_bmp (php_stream * stream)
{
struct gfxinfo *result = NULL;
char temp[15];
@@ -133,8 +133,8 @@ static struct gfxinfo *php_handle_bmp (int socketd, FILE *fp, int issock)
result = (struct gfxinfo *) ecalloc (1, sizeof(struct gfxinfo));
- FP_FREAD(temp, sizeof(temp), socketd, fp, issock);
- FP_FREAD((char*) &dim, sizeof(dim), socketd, fp, issock);
+ php_stream_read(stream, temp, sizeof(temp));
+ php_stream_read(stream, (char*) &dim, sizeof(dim));
result->width = dim.in_width;
result->height = dim.in_height;
@@ -160,7 +160,7 @@ static unsigned long int php_swf_get_bits (unsigned char* buffer, unsigned int p
/* {{{ php_handle_swf
*/
-static struct gfxinfo *php_handle_swf (int socketd, FILE *fp, int issock)
+static struct gfxinfo *php_handle_swf (php_stream * stream)
{
struct gfxinfo *result = NULL;
long bits;
@@ -168,9 +168,9 @@ static struct gfxinfo *php_handle_swf (int socketd, FILE *fp, int issock)
char temp[5];
result = (struct gfxinfo *) ecalloc (1, sizeof (struct gfxinfo));
- FP_FREAD(temp, 5, socketd, fp, issock); /* fseek(fp, 8L, SEEK_SET); */
+ php_stream_read(stream, temp, 5); /* fseek(fp, 8L, SEEK_SET); */
- FP_FREAD(a, sizeof(a), socketd, fp, issock); /* fread(a, sizeof(a), 1, fp); */
+ php_stream_read(stream, a, sizeof(a)); /* fread(a, sizeof(a), 1, fp); */
bits = php_swf_get_bits (a, 0, 5);
result->width = (php_swf_get_bits (a, 5 + bits, bits) -
php_swf_get_bits (a, 5, bits)) / 20;
@@ -182,7 +182,7 @@ static struct gfxinfo *php_handle_swf (int socketd, FILE *fp, int issock)
/* {{{ php_handle_png
* routine to handle PNG files */
-static struct gfxinfo *php_handle_png (int socketd, FILE *fp, int issock)
+static struct gfxinfo *php_handle_png (php_stream * stream)
{
struct gfxinfo *result = NULL;
unsigned long in_width, in_height;
@@ -191,9 +191,9 @@ static struct gfxinfo *php_handle_png (int socketd, FILE *fp, int issock)
result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
- FP_FREAD(temp, sizeof(temp), socketd, fp, issock); /* fseek(fp, 16L, SEEK_SET); */
+ php_stream_read(stream, temp, sizeof(temp)); /* fseek(fp, 16L, SEEK_SET); */
- if((FP_FREAD(a, sizeof(a), socketd, fp, issock)) <= 0) {
+ if((php_stream_read(stream, a, sizeof(a))) <= 0) {
in_width = 0;
in_height = 0;
} else {
@@ -248,12 +248,12 @@ static struct gfxinfo *php_handle_png (int socketd, FILE *fp, int issock)
/* {{{ php_read2
*/
-static unsigned short php_read2(int socketd, FILE *fp, int issock)
+static unsigned short php_read2(php_stream * stream)
{
unsigned char a[2];
/* just return 0 if we hit the end-of-file */
- if((FP_FREAD(a, sizeof(a), socketd, fp, issock)) <= 0) return 0;
+ if((php_stream_read(stream, a, sizeof(a))) <= 0) return 0;
return (((unsigned short) a[ 0 ]) << 8) + ((unsigned short) a[ 1 ]);
}
@@ -261,7 +261,7 @@ static unsigned short php_read2(int socketd, FILE *fp, int issock)
/* {{{ php_next_marker
* get next marker byte from file */
-static unsigned int php_next_marker(int socketd, FILE *fp, int issock, int last_marker, int comment_correction, int ff_read)
+static unsigned int php_next_marker(php_stream * stream, int last_marker, int comment_correction, int ff_read)
{
int a=0, marker;
@@ -279,7 +279,7 @@ static unsigned int php_next_marker(int socketd, FILE *fp, int issock, int last_
a = 1; /* already read 0xff in filetype detection */
}
do {
- if ((marker = FP_FGETC(socketd, fp, issock)) == EOF)
+ if ((marker = php_stream_getc(stream)) == EOF)
{
return M_EOI;/* we hit EOF */
}
@@ -312,52 +312,31 @@ static unsigned int php_next_marker(int socketd, FILE *fp, int issock, int last_
}
/* }}} */
-/* {{{ php_skip_over
- * skip over a block of specified length */
-#ifndef FP_FSKIP
-
-#define FP_FSKIP(l,socketd,fp,issock) php_skip_over(socketd,fp,issock,l)
-
-static void php_skip_over(int socketd, FILE *fp, int issock, size_t length)
-{
- static char tmp[1024];
-
- while(length>=sizeof(tmp)) {
- FP_FREAD(tmp, sizeof(tmp), socketd, fp, issock);
- length -= sizeof(tmp);
- }
- if(length) {
- FP_FREAD(tmp, length, socketd, fp, issock);
- }
-}
-#endif
-/* }}} */
-
/* {{{ php_skip_variable
* skip over a variable-length block; assumes proper length marker */
-static void php_skip_variable(int socketd, FILE *fp, int issock)
+static void php_skip_variable(php_stream * stream)
{
- size_t length = php_read2(socketd, fp, issock);
- FP_FSKIP( length-2, socketd, fp, issock);
+ size_t length = php_read2(stream);
+ php_stream_seek(stream, SEEK_CUR, length-2);
}
/* }}} */
/* {{{ php_read_APP
*/
-static void php_read_APP(int socketd, FILE *fp, int issock, unsigned int marker, zval *info)
+static void php_read_APP(php_stream * stream, unsigned int marker, zval *info)
{
unsigned short length;
unsigned char *buffer;
unsigned char markername[ 16 ];
zval *tmp;
- length = php_read2(socketd, fp, issock);
+ length = php_read2(stream);
length -= 2; /* length includes itself */
buffer = emalloc(length);
if ( !buffer) return;
- if (FP_FREAD(buffer, (long) length, socketd, fp, issock) <= 0) {
+ if (php_stream_read(stream, buffer, (long) length) <= 0) {
efree(buffer);
return;
}
@@ -375,14 +354,14 @@ static void php_read_APP(int socketd, FILE *fp, int issock, unsigned int marker,
/* {{{ php_handle_jpeg
main loop to parse JPEG structure */
-static struct gfxinfo *php_handle_jpeg (int socketd, FILE *fp, int issock, pval *info)
+static struct gfxinfo *php_handle_jpeg (php_stream * stream, pval *info)
{
struct gfxinfo *result = NULL;
unsigned int marker = M_PSEUDO;
unsigned short length, ff_read=1;
for (;;) {
- marker = php_next_marker(socketd, fp, issock, marker, 1, ff_read);
+ marker = php_next_marker(stream, marker, 1, ff_read);
ff_read = 0;
switch (marker) {
case M_SOF0:
@@ -403,16 +382,16 @@ static struct gfxinfo *php_handle_jpeg (int socketd, FILE *fp, int issock, pval
result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
if ( !result)
return NULL;
- length = php_read2(socketd, fp, issock);
- result->bits = FP_FGETC(socketd, fp, issock);
- result->height = php_read2(socketd, fp, issock);
- result->width = php_read2(socketd, fp, issock);
- result->channels = FP_FGETC(socketd, fp, issock);
+ length = php_read2(stream);
+ result->bits = php_stream_getc(stream);
+ result->height = php_read2(stream);
+ result->width = php_read2(stream);
+ result->channels = php_stream_getc(stream);
if (!info || length<8) /* if we don't want an extanded info -> return */
return result;
- FP_FSKIP( length-8, socketd, fp, issock);
+ php_stream_seek(stream, SEEK_CUR, length-8);
} else {
- php_skip_variable(socketd, fp, issock);
+ php_skip_variable(stream);
}
break;
@@ -433,9 +412,9 @@ static struct gfxinfo *php_handle_jpeg (int socketd, FILE *fp, int issock, pval
case M_APP14:
case M_APP15:
if (info) {
- php_read_APP(socketd, fp, issock, marker, info); /* read all the app markes... */
+ php_read_APP(stream, marker, info); /* read all the app markes... */
} else {
- php_skip_variable(socketd, fp, issock);
+ php_skip_variable(stream);
}
break;
@@ -445,7 +424,7 @@ static struct gfxinfo *php_handle_jpeg (int socketd, FILE *fp, int issock, pval
break;
default:
- php_skip_variable(socketd, fp, issock); /* anything else isn't interesting */
+ php_skip_variable(stream); /* anything else isn't interesting */
break;
}
}
@@ -462,12 +441,12 @@ static struct gfxinfo *php_handle_jpeg (int socketd, FILE *fp, int issock, pval
/* {{{ php_read4
*/
-static unsigned int php_read4(int socketd, FILE *fp, int issock)
+static unsigned int php_read4(php_stream * stream)
{
unsigned char a[4];
/* just return 0 if we hit the end-of-file */
- if((FP_FREAD(a, sizeof(a), socketd, fp, issock)) <= 0) return 0;
+ if((php_stream_read(stream, a, sizeof(a))) <= 0) return 0;
return (((unsigned int)a[0]) << 24)
+ (((unsigned int)a[1]) << 16)
@@ -478,32 +457,32 @@ static unsigned int php_read4(int socketd, FILE *fp, int issock)
/* {{{ php_handle_tiff
main loop to parse TIFF structure */
-static struct gfxinfo *php_handle_jpc(int socketd, FILE *fp, int issock)
+static struct gfxinfo *php_handle_jpc(php_stream * stream)
{
struct gfxinfo *result = NULL;
unsigned int marker, dummy;
unsigned short length, ff_read = 1;
- marker = php_next_marker(socketd, fp, issock, 0, 0, ff_read);
+ marker = php_next_marker(stream, 0, 0, ff_read);
ff_read = 0;
if ( marker == JC_SIZ)
{
- length = php_read2(socketd, fp, issock); /* Lsiz: length of segment */
+ length = php_read2(stream); /* Lsiz: length of segment */
if ( length<42 || length>49191) /* read the spec */
return NULL;
result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
if ( !result)
return NULL;
- dummy = php_read2(socketd, fp, issock); /* Rsiz: capabilities */
- result->height = php_read4(socketd, fp, issock); /* Xsiz */
- result->width = php_read4(socketd, fp, issock); /* Ysiz */
- dummy = php_read4(socketd, fp, issock); /* X0siz */
- dummy = php_read4(socketd, fp, issock); /* Y0siz */
- dummy = php_read4(socketd, fp, issock); /* XTsiz */
- dummy = php_read4(socketd, fp, issock); /* YTsiz */
- dummy = php_read4(socketd, fp, issock); /* XT0siz */
- dummy = php_read4(socketd, fp, issock); /* YT0siz */
- result->bits = php_read2(socketd, fp, issock); /* Csiz: precision in bitss */
+ dummy = php_read2(stream); /* Rsiz: capabilities */
+ result->height = php_read4(stream); /* Xsiz */
+ result->width = php_read4(stream); /* Ysiz */
+ dummy = php_read4(stream); /* X0siz */
+ dummy = php_read4(stream); /* Y0siz */
+ dummy = php_read4(stream); /* XTsiz */
+ dummy = php_read4(stream); /* YTsiz */
+ dummy = php_read4(stream); /* XT0siz */
+ dummy = php_read4(stream); /* YT0siz */
+ result->bits = php_read2(stream); /* Csiz: precision in bitss */
result->channels = 0; /* don't know yet */
return result;
}
@@ -582,7 +561,7 @@ static unsigned php_ifd_get32u(void *Long, int motorola_intel)
/* {{{ php_handle_tiff
main loop to parse TIFF structure */
-static struct gfxinfo *php_handle_tiff (int socketd, FILE *fp, int issock, pval *info, int motorola_intel)
+static struct gfxinfo *php_handle_tiff (php_stream * stream, pval *info, int motorola_intel)
{
struct gfxinfo *result = NULL;
int i, num_entries;
@@ -591,17 +570,17 @@ static struct gfxinfo *php_handle_tiff (int socketd, FILE *fp, int issock, pval
int entry_tag , entry_type;
char *ifd_data, ifd_ptr[4];
- FP_FREAD(ifd_ptr, 4, socketd, fp, issock);
+ php_stream_read(stream, ifd_ptr, 4);
ifd_addr = php_ifd_get32u(ifd_ptr, motorola_intel);
- FP_FSKIP(ifd_addr-8, socketd, fp, issock);
+ php_stream_seek(stream, SEEK_CUR, ifd_addr-8);
ifd_size = 2;
ifd_data = emalloc(ifd_size);
- FP_FREAD(ifd_data, 2, socketd, fp, issock);
+ php_stream_read(stream, ifd_data, 2);
num_entries = php_ifd_get16u(ifd_data, motorola_intel);
dir_size = 2/*num dir entries*/ +12/*length of entry*/*num_entries +4/* offset to next ifd (points to thumbnail or NULL)*/;
ifd_size = dir_size;
ifd_data = erealloc(ifd_data,ifd_size);
- FP_FREAD(ifd_data+2, dir_size-2, socketd, fp, issock);
+ php_stream_read(stream, ifd_data+2, dir_size-2);
/* now we have the directory we can look how long it should be */
ifd_size = dir_size;
for(i=0;i<num_entries;i++) {
@@ -654,12 +633,12 @@ static struct gfxinfo *php_handle_tiff (int socketd, FILE *fp, int issock, pval
/* {{{ php_imagetype
detect filetype from first bytes */
-int php_getimagetype(int socketd, FILE *fp, int issock, char *filetype)
+int php_getimagetype(php_stream * stream, char *filetype)
{
char tmp[8];
if ( !filetype) filetype = tmp;
- if((FP_FREAD(filetype, 3, socketd, fp, issock)) <= 0) {
+ if((php_stream_read(stream, filetype, 3)) <= 0) {
php_error(E_WARNING, "getimagesize: Read error!");
return IMAGE_FILETYPE_UNKNOWN;
}
@@ -669,7 +648,7 @@ int php_getimagetype(int socketd, FILE *fp, int issock, char *filetype)
} else if (!memcmp(filetype, php_sig_jpg, 3)) {
return IMAGE_FILETYPE_JPEG;
} else if (!memcmp(filetype, php_sig_png, 3)) {
- FP_FREAD(filetype+3, 5, socketd, fp, issock);
+ php_stream_read(stream, filetype+3, 5);
if (!memcmp(filetype, php_sig_png, 8)) {
return IMAGE_FILETYPE_PNG;
} else {
@@ -685,7 +664,7 @@ int php_getimagetype(int socketd, FILE *fp, int issock, char *filetype)
} else if (!memcmp(filetype, php_sig_jpc, 3)) {
return IMAGE_FILETYPE_JPC;
} else {
- FP_FREAD(filetype+3, 1, socketd, fp, issock);
+ php_stream_read(stream, filetype+3, 1);
if (!memcmp(filetype, php_sig_tif_ii, 4)) {
return IMAGE_FILETYPE_TIFF_II;
} else
@@ -703,11 +682,11 @@ int php_getimagetype(int socketd, FILE *fp, int issock, char *filetype)
PHP_FUNCTION(getimagesize)
{
zval **arg1, **info = NULL;
- FILE *fp;
- int issock=0, socketd=0, rsrc_id;
+ int rsrc_id;
int itype = 0;
char temp[64];
struct gfxinfo *result = NULL;
+ php_stream * stream = NULL;
switch(ZEND_NUM_ARGS()) {
@@ -736,58 +715,46 @@ PHP_FUNCTION(getimagesize)
break;
}
- fp = php_fopen_wrapper(Z_STRVAL_PP(arg1), "rb", IGNORE_PATH|ENFORCE_SAFE_MODE, &issock, &socketd, NULL TSRMLS_CC);
+ stream = php_stream_open_wrapper(Z_STRVAL_PP(arg1), "rb", REPORT_ERRORS|IGNORE_PATH|ENFORCE_SAFE_MODE, NULL TSRMLS_CC);
- if (!fp && !socketd) {
- if (issock != BAD_URL) {
- char *tmp = estrndup(Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1));
- php_strip_url_passwd(tmp);
- php_error(E_WARNING, "getimagesize: Unable to open '%s' for reading.", tmp);
- efree(tmp);
- }
+ if (!stream) {
RETURN_FALSE;
}
- if (issock) {
- int *sock=emalloc(sizeof(int));
- *sock = socketd;
- rsrc_id = ZEND_REGISTER_RESOURCE(NULL, sock, php_file_le_socket());
- } else {
- rsrc_id = ZEND_REGISTER_RESOURCE(NULL, fp, php_file_le_fopen());
- }
+ rsrc_id = ZEND_REGISTER_RESOURCE(NULL, stream, php_file_le_stream());
- itype = php_getimagetype(socketd, fp, issock, NULL);
+ itype = php_getimagetype(stream, NULL);
switch( itype) {
case IMAGE_FILETYPE_GIF:
- result = php_handle_gif (socketd, fp, issock);
+ result = php_handle_gif (stream);
break;
case IMAGE_FILETYPE_JPEG:
if (info) {
- result = php_handle_jpeg(socketd, fp, issock, *info);
+ result = php_handle_jpeg(stream, *info);
} else {
- result = php_handle_jpeg(socketd, fp, issock, NULL);
+ result = php_handle_jpeg(stream, NULL);
}
break;
case IMAGE_FILETYPE_PNG:
- result = php_handle_png(socketd, fp, issock);
+ result = php_handle_png(stream);
break;
case IMAGE_FILETYPE_SWF:
- result = php_handle_swf(socketd, fp, issock);
+ result = php_handle_swf(stream);
break;
case IMAGE_FILETYPE_PSD:
- result = php_handle_psd(socketd, fp, issock);
+ result = php_handle_psd(stream);
break;
case IMAGE_FILETYPE_BMP:
- result = php_handle_bmp(socketd, fp, issock);
+ result = php_handle_bmp(stream);
break;
case IMAGE_FILETYPE_TIFF_II:
- result = php_handle_tiff(socketd, fp, issock, NULL, 0);
+ result = php_handle_tiff(stream, NULL, 0);
break;
case IMAGE_FILETYPE_TIFF_MM:
- result = php_handle_tiff(socketd, fp, issock, NULL, 1);
+ result = php_handle_tiff(stream, NULL, 1);
break;
case IMAGE_FILETYPE_JPC:
- result = php_handle_jpc(socketd, fp, issock);
+ result = php_handle_jpc(stream);
break;
default:
case IMAGE_FILETYPE_UNKNOWN:
diff --git a/ext/standard/info.c b/ext/standard/info.c
index 026e00db87..ac0d5560e6 100644
--- a/ext/standard/info.c
+++ b/ext/standard/info.c
@@ -211,9 +211,7 @@ PHPAPI void php_print_info(int flag TSRMLS_DC)
php_info_print_table_row(2, "Thread Safety", "disabled" );
#endif
-#if HAVE_PHP_STREAM
- php_info_print_table_row(2, "Experimental PHP Streams", "enabled");
-#endif
+ php_info_print_table_row(2, "PHP Streams", "enabled");
php_info_print_table_end();
diff --git a/ext/standard/php_fopen_wrapper.c b/ext/standard/php_fopen_wrapper.c
index 26c9ec2a9e..37b3b2b90f 100644
--- a/ext/standard/php_fopen_wrapper.c
+++ b/ext/standard/php_fopen_wrapper.c
@@ -30,26 +30,33 @@
#include "php_standard.h"
#include "php_fopen_wrappers.h"
-
-/* {{{ php_fopen_url_wrap_php
- */
-FILE *php_fopen_url_wrap_php(const char *path, char *mode, int options, int *issock, int *socketd, char **opened_path TSRMLS_DC)
+php_stream * php_stream_url_wrap_php(char * path, char * mode, int options, char ** opened_path TSRMLS_DC)
{
- const char *res = path + 6;
-
- *issock = 0;
+ FILE * fp = NULL;
+ php_stream * stream = NULL;
- if (!strcasecmp(res, "stdin")) {
- return fdopen(dup(STDIN_FILENO), mode);
- } else if (!strcasecmp(res, "stdout")) {
- return fdopen(dup(STDOUT_FILENO), mode);
- } else if (!strcasecmp(res, "stderr")) {
- return fdopen(dup(STDERR_FILENO), mode);
+ if (!strcasecmp(path, "stdin")) {
+ fp = fdopen(dup(STDIN_FILENO), mode);
+ } else if (!strcasecmp(path, "stdout")) {
+ fp = fdopen(dup(STDOUT_FILENO), mode);
+ } else if (!strcasecmp(path, "stderr")) {
+ fp = fdopen(dup(STDERR_FILENO), mode);
}
-
- return NULL;
+ /* TODO: implement php://output as a stream to write to the current output buffer ? */
+
+ if (fp) {
+ stream = php_stream_fopen_from_file(fp, mode);
+ if (stream == NULL)
+ fclose(fp);
+ }
+ return stream;
}
-/* }}} */
+
+php_stream_wrapper php_stream_php_wrapper = {
+ php_stream_url_wrap_php,
+ NULL
+};
+
/*
* Local variables:
diff --git a/ext/standard/php_fopen_wrappers.h b/ext/standard/php_fopen_wrappers.h
index 0cab1fe73e..1cad9777c9 100644
--- a/ext/standard/php_fopen_wrappers.h
+++ b/ext/standard/php_fopen_wrappers.h
@@ -23,8 +23,10 @@
#ifndef PHP_FOPEN_WRAPPERS_H
#define PHP_FOPEN_WRAPPERS_H
-FILE *php_fopen_url_wrap_http(const char *, char *, int, int *, int *, char ** TSRMLS_DC);
-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);
+php_stream * php_stream_url_wrap_http(char * path, char * mode, int options, char ** opened_path TSRMLS_DC);
+php_stream * php_stream_url_wrap_ftp(char * path, char * mode, int options, char ** opened_path TSRMLS_DC);
+php_stream_wrapper php_stream_http_wrapper;
+php_stream_wrapper php_stream_ftp_wrapper;
+php_stream_wrapper php_stream_php_wrapper;
#endif
diff --git a/ext/standard/php_image.h b/ext/standard/php_image.h
index 1837bab6a2..3046c8cd62 100644
--- a/ext/standard/php_image.h
+++ b/ext/standard/php_image.h
@@ -45,6 +45,6 @@ typedef enum
} image_filetype;
/* }}} */
-extern int php_getimagetype(int socketd, FILE *fp, int issock, char *filetype);
+extern int php_getimagetype(php_stream * stream, char *filetype);
#endif /* PHP_IMAGE_H */
diff --git a/ext/zlib/php_zlib.h b/ext/zlib/php_zlib.h
index 7a9b0de247..bedc65c587 100644
--- a/ext/zlib/php_zlib.h
+++ b/ext/zlib/php_zlib.h
@@ -67,6 +67,9 @@ PHP_FUNCTION(ob_gzhandler);
FILE *zlib_fopen_wrapper(const char *path, char *mode, int options, int *issock, int *socketd, char **opened_path TSRMLS_DC);
int php_enable_output_compression(int buffer_size TSRMLS_DC);
+php_stream * php_stream_gzopen(char * path, char * mode, int options, char ** opened_path TSRMLS_DC);
+extern php_stream_ops php_stream_gzio_ops;
+extern php_stream_wrapper php_stream_gzip_wrapper;
#ifdef ZTS
#define ZLIBG(v) TSRMG(zlib_globals_id, zend_zlib_globals *, v)
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index fdb54ca76e..1b39fb0399 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -187,12 +187,9 @@ PHP_MINIT_FUNCTION(zlib)
#endif
le_zp = zend_register_list_destructors_ex(phpi_destructor_gzclose, NULL, "zlib", module_number);
-#if HAVE_FOPENCOOKIE
-
if(PG(allow_url_fopen)) {
- php_register_url_wrapper("zlib", zlib_fopen_wrapper TSRMLS_CC);
+ php_register_url_stream_wrapper("zlib", &php_stream_gzip_wrapper TSRMLS_CC);
}
-#endif
REGISTER_LONG_CONSTANT("FORCE_GZIP", CODING_GZIP, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("FORCE_DEFLATE", CODING_DEFLATE, CONST_CS | CONST_PERSISTENT);
@@ -225,11 +222,8 @@ PHP_RINIT_FUNCTION(zlib)
*/
PHP_MSHUTDOWN_FUNCTION(zlib)
{
-#if HAVE_FOPENCOOKIE
- if(PG(allow_url_fopen)) {
- php_unregister_url_wrapper("zlib" TSRMLS_CC);
- }
-#endif
+ if (PG(allow_url_fopen))
+ php_unregister_url_stream_wrapper("zlib" TSRMLS_CC);
UNREGISTER_INI_ENTRIES();
@@ -258,15 +252,23 @@ PHP_MINFO_FUNCTION(zlib)
*/
static gzFile php_gzopen_wrapper(char *path, char *mode, int options TSRMLS_DC)
{
- FILE *f;
- int issock=0, socketd=0;
-
- f = php_fopen_wrapper(path, mode, options, &issock, &socketd, NULL TSRMLS_CC);
-
- if (!f) {
- return NULL;
+ php_stream * stream = NULL;
+ int fd;
+
+ stream = php_stream_open_wrapper(path, mode, options | REPORT_ERRORS, NULL TSRMLS_CC);
+ if (stream) {
+ if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD | PHP_STREAM_CAST_TRY_HARD, (void**)&fd, 1))
+ {
+ gzFile ret = gzdopen(fd, mode);
+ if (ret) {
+ /* arrange to clean up the actual stream */
+ ZEND_REGISTER_RESOURCE(NULL, stream, php_file_le_stream());
+ return ret;
+ }
+ }
+ php_stream_close(stream);
}
- return gzdopen(fileno(f), mode);
+ return NULL;
}
/* }}} */
@@ -275,10 +277,10 @@ static gzFile php_gzopen_wrapper(char *path, char *mode, int options TSRMLS_DC)
PHP_FUNCTION(gzfile)
{
pval **filename, **arg2;
- gzFile zp;
char *slashed, buf[8192];
register int i=0;
int use_include_path = 0;
+ php_stream * stream;
/* check args */
switch (ZEND_NUM_ARGS()) {
@@ -299,8 +301,9 @@ PHP_FUNCTION(gzfile)
}
convert_to_string_ex(filename);
- zp = php_gzopen_wrapper(Z_STRVAL_PP(filename),"r", use_include_path|ENFORCE_SAFE_MODE TSRMLS_CC);
- if (!zp) {
+ /* using a stream here is a bit more efficient (resource wise) than php_gzopen_wrapper */
+ stream = php_stream_gzopen(Z_STRVAL_PP(filename), "r", use_include_path|ENFORCE_SAFE_MODE, NULL TSRMLS_CC);
+ if (!stream) {
php_error(E_WARNING,"gzFile(\"%s\") - %s",Z_STRVAL_PP(filename),strerror(errno));
RETURN_FALSE;
}
@@ -311,8 +314,8 @@ PHP_FUNCTION(gzfile)
}
/* Now loop through the file and do the magic quotes thing if needed */
- memset(buf,0,8191);
- while(gzgets(zp, buf, 8191) != NULL) {
+ memset(buf,0,sizeof(buf));
+ while(php_stream_gets(stream, buf, sizeof(buf)-1) != NULL) {
if (PG(magic_quotes_runtime)) {
int len;
@@ -322,7 +325,7 @@ PHP_FUNCTION(gzfile)
add_index_string(return_value, i++, buf, 1);
}
}
- gzclose(zp);
+ php_stream_close(stream);
}
/* }}} */
diff --git a/ext/zlib/zlib_fopen_wrapper.c b/ext/zlib/zlib_fopen_wrapper.c
index 2ca7aa77f1..5a59d023ab 100644
--- a/ext/zlib/zlib_fopen_wrapper.c
+++ b/ext/zlib/zlib_fopen_wrapper.c
@@ -23,78 +23,104 @@
#include "php_zlib.h"
#include "fopen_wrappers.h"
-#if HAVE_FOPENCOOKIE
-
-
-struct gz_cookie {
+struct php_gz_stream_data_t {
gzFile gz_file;
+ php_stream * stream;
};
-static ssize_t gz_reader(void *cookie, char *buffer, size_t size)
+static size_t php_gziop_read(php_stream * stream, char * buf, size_t count)
{
- return gzread(((struct gz_cookie *)cookie)->gz_file,buffer,size);
+ struct php_gz_stream_data_t * self = (struct php_gz_stream_data_t *)stream->abstract;
+
+ if (buf == NULL && count == 0) {
+ if (gzeof(self->gz_file))
+ return EOF;
+ return 0;
+ }
+
+ return gzread(self->gz_file, buf, count);
}
-static ssize_t gz_writer(void *cookie, const char *buffer, size_t size) {
- return gzwrite(((struct gz_cookie *)cookie)->gz_file,(char *)buffer,size);
+static char * php_gziop_gets(php_stream * stream, char * buf, size_t size)
+{
+ struct php_gz_stream_data_t * self = (struct php_gz_stream_data_t *)stream->abstract;
+ return gzgets(self->gz_file, buf, size);
}
-static int gz_seeker(void *cookie,off_t position, int whence) {
- return gzseek(((struct gz_cookie *)cookie)->gz_file,(z_off_t)position,whence);
+
+static size_t php_gziop_write(php_stream * stream, const char * buf, size_t count)
+{
+ struct php_gz_stream_data_t * self = (struct php_gz_stream_data_t *)stream->abstract;
+ return gzwrite(self->gz_file, (char*)buf, count);
}
-static int gz_closer(void *cookie) {
- int ret=gzclose(((struct gz_cookie *)cookie)->gz_file);
- free(cookie);
- cookie=NULL;
- return ret;
+static int php_gziop_seek(php_stream * stream, off_t offset, int whence)
+{
+ struct php_gz_stream_data_t * self = (struct php_gz_stream_data_t *)stream->abstract;
+ return gzseek(self->gz_file, offset, whence);
}
+static int php_gziop_close(php_stream * stream)
+{
+ struct php_gz_stream_data_t * self = (struct php_gz_stream_data_t *)stream->abstract;
+ int ret;
+
+ ret = gzclose(self->gz_file);
+ php_stream_close(self->stream);
+ efree(self);
+ return ret;
+}
-static COOKIE_IO_FUNCTIONS_T gz_cookie_functions =
-{ gz_reader
-, gz_writer
-, gz_seeker
-, gz_closer
+php_stream_ops php_stream_gzio_ops = {
+ php_gziop_write, php_gziop_read,
+ php_gziop_close, NULL,
+ php_gziop_seek, php_gziop_gets,
+ NULL, "ZLIB"
};
-FILE *zlib_fopen_wrapper(const char *path, char *mode, int options, int *issock, int *socketd, char **opened_path TSRMLS_DC)
+php_stream * php_stream_gzopen(char * path, char * mode, int options, char ** opened_path TSRMLS_DC)
{
- struct gz_cookie *gc = NULL;
- FILE *fp;
- int fissock=0, fsocketd=0;
-
- gc = (struct gz_cookie *)malloc(sizeof(struct gz_cookie));
-
- if(gc) {
- *issock = 0;
-
- while(*path!=':')
- path++;
-
+ struct php_gz_stream_data_t * self;
+ php_stream * stream = NULL;
+
+ self = emalloc(sizeof(*self));
+
+ while(*path != ':')
path++;
-
- fp = php_fopen_wrapper((char *) path, mode, options|IGNORE_URL, &fissock, &fsocketd, NULL TSRMLS_CC);
-
- if (!fp) {
- free(gc);
- return NULL;
- }
-
- gc->gz_file = gzdopen(fileno(fp), mode);
-
- if(gc->gz_file) {
- return fopencookie(gc,mode,gz_cookie_functions);
- } else {
- free(gc);
- return NULL;
+ path++;
+
+ self->stream = php_stream_open_wrapper(path, mode, options, opened_path TSRMLS_CC);
+
+ if (self->stream) {
+ int fd;
+ if (SUCCESS == php_stream_cast(self->stream, PHP_STREAM_AS_FD, (void**)&fd, REPORT_ERRORS)) {
+ self->gz_file = gzdopen(fd, mode);
+ if (self->gz_file) {
+ stream = php_stream_alloc(&php_stream_gzio_ops, self, 0, mode);
+ if (stream)
+ return stream;
+ gzclose(self->gz_file);
+ }
}
}
- errno = ENOENT;
+ if (stream)
+ php_stream_close(stream);
+ if (self && self->stream)
+ php_stream_close(self->stream);
+ if (self)
+ efree(self);
+
return NULL;
}
-#endif
+
+php_stream_wrapper php_stream_gzip_wrapper = {
+ php_stream_gzopen,
+ NULL
+};
+
+
+
/*
* Local variables:
diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c
index 7cf55651d4..9bbd126571 100644
--- a/main/fopen_wrappers.c
+++ b/main/fopen_wrappers.c
@@ -82,55 +82,6 @@
#endif
/* }}} */
-static FILE *php_fopen_url_wrapper(const char *, char *, int, int *, int *, char ** TSRMLS_DC);
-static HashTable fopen_url_wrappers_hash;
-
-/* {{{ php_register_url_wrapper
- */
-PHPAPI int php_register_url_wrapper(const char *protocol, php_fopen_url_wrapper_t wrapper TSRMLS_DC)
-{
- if(PG(allow_url_fopen)) {
- return zend_hash_add(&fopen_url_wrappers_hash, (char *) protocol, strlen(protocol), &wrapper, sizeof(wrapper), NULL);
- } else {
- return FAILURE;
- }
-}
-/* }}} */
-
-/* {{{ php_unregister_url_wrapper
- */
-PHPAPI int php_unregister_url_wrapper(char *protocol TSRMLS_DC)
-{
- if(PG(allow_url_fopen)) {
- return zend_hash_del(&fopen_url_wrappers_hash, protocol, strlen(protocol));
- } else {
- return SUCCESS;
- }
-}
-/* }}} */
-
-/* {{{ php_init_fopen_wrappers
- */
-int php_init_fopen_wrappers(TSRMLS_D)
-{
- if(PG(allow_url_fopen)) {
- return zend_hash_init(&fopen_url_wrappers_hash, 0, NULL, NULL, 1);
- }
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ php_shutdown_fopen_wrappers
- */
-int php_shutdown_fopen_wrappers(TSRMLS_D)
-{
- if(PG(allow_url_fopen)) {
- zend_hash_destroy(&fopen_url_wrappers_hash);
- }
- return SUCCESS;
-}
-/* }}} */
-
/* {{{ php_check_specific_open_basedir
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
@@ -289,36 +240,6 @@ static FILE *php_fopen_and_set_opened_path(const char *path, char *mode, char **
}
/* }}} */
-/* {{{ php_fopen_wrapper
- */
-PHPAPI FILE *php_fopen_wrapper(char *path, char *mode, int options, int *issock, int *socketd, char **opened_path TSRMLS_DC)
-{
- if (opened_path) {
- *opened_path = NULL;
- }
-
- if(!path || !*path) {
- return NULL;
- }
-
-
- if(PG(allow_url_fopen)) {
- if (!(options & IGNORE_URL)) {
- return php_fopen_url_wrapper(path, mode, options, issock, socketd, opened_path TSRMLS_CC);
- }
- }
-
- if (options & USE_PATH && PG(include_path) != NULL) {
- return php_fopen_with_path(path, mode, PG(include_path), opened_path TSRMLS_CC);
- } else {
- if (options & ENFORCE_SAFE_MODE && PG(safe_mode) && (!php_checkuid(path, mode, CHECKUID_CHECK_MODE_PARAM))) {
- return NULL;
- }
- return php_fopen_and_set_opened_path(path, mode, opened_path TSRMLS_CC);
- }
-}
-/* }}} */
-
/* {{{ php_fopen_primary_script
*/
PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle TSRMLS_DC)
@@ -535,64 +456,6 @@ PHPAPI FILE *php_fopen_with_path(char *filename, char *mode, char *path, char **
}
/* }}} */
-/* {{{ php_fopen_url_wrapper
- */
-static FILE *php_fopen_url_wrapper(const char *path, char *mode, int options, int *issock, int *socketd, char **opened_path TSRMLS_DC)
-{
- FILE *fp = NULL;
- const char *p;
- const char *protocol=NULL;
- int n=0;
-
- for (p=path; isalnum((int)*p); p++) {
- n++;
- }
- if ((*p==':')&&(n>1)) {
- protocol=path;
- }
-
- if (protocol) {
- php_fopen_url_wrapper_t *wrapper=NULL;
-
- if (FAILURE==zend_hash_find(&fopen_url_wrappers_hash, (char *) protocol, n, (void **)&wrapper)) {
- wrapper=NULL;
- protocol=NULL;
- }
- if (wrapper) {
- return (*wrapper)(path, mode, options, issock, socketd, opened_path TSRMLS_CC);
- }
- }
-
- if (!protocol || !strncasecmp(protocol, "file", n)){
- *issock = 0;
-
- if(protocol) {
- if(path[n+1]=='/') {
- if(path[n+2]=='/') {
- php_error(E_WARNING, "remote host file access not supported, %s", path);
- return NULL;
- }
- }
- path+= n+1;
- }
-
- if (options & USE_PATH) {
- fp = php_fopen_with_path((char *) path, mode, PG(include_path), opened_path TSRMLS_CC);
- } else {
- if (options & ENFORCE_SAFE_MODE && PG(safe_mode) && (!php_checkuid(path, mode, CHECKUID_CHECK_MODE_PARAM))) {
- fp = NULL;
- } else {
- fp = php_fopen_and_set_opened_path(path, mode, opened_path TSRMLS_CC);
- }
- }
- return (fp);
- }
-
- php_error(E_WARNING, "Invalid URL specified, %s", path);
- return NULL;
-}
-/* }}} */
-
/* {{{ php_strip_url_passwd
*/
PHPAPI char *php_strip_url_passwd(char *url)
diff --git a/main/fopen_wrappers.h b/main/fopen_wrappers.h
index dc28af9f47..24e60dcc00 100644
--- a/main/fopen_wrappers.h
+++ b/main/fopen_wrappers.h
@@ -27,12 +27,14 @@
#define IGNORE_URL 2
/* There's no USE_URL. */
#ifdef PHP_WIN32
-# define IGNORE_URL_WIN 2
+# define IGNORE_URL_WIN IGNORE_URL
#else
# define IGNORE_URL_WIN 0
#endif
#define ENFORCE_SAFE_MODE 4
+#define REPORT_ERRORS 8
+
#ifdef PHP_WIN32
# define SOCK_ERR INVALID_SOCKET
# define SOCK_CONN_ERR SOCKET_ERROR
@@ -42,22 +44,6 @@
# define SOCK_CONN_ERR -1
# define SOCK_RECV_ERR -1
#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(s) php_sock_fgetc((s))
-#define SOCK_FGETS(b, l, s) php_sock_fgets((b), (l), (s))
-#define SOCK_FEOF(sock) php_sock_feof((sock))
-#define SOCK_FREAD(ptr, size, sock) php_sock_fread((ptr), (size), (sock))
-#define SOCK_FCLOSE(s) php_sock_close(s)
-
-#define FP_FGETS(buf, len, sock, fp, issock) \
- ((issock)?SOCK_FGETS(buf, len, sock):fgets(buf, len, fp))
-#define FP_FREAD(buf, len, sock, fp, issock) \
- ((issock)?SOCK_FREAD(buf, len, sock):fread(buf, 1, len, fp))
-#define FP_FEOF(sock, fp, issock) \
- ((issock)?SOCK_FEOF(sock):feof(fp))
-#define FP_FGETC(sock, fp, issock) \
- ((issock)?SOCK_FGETC(sock):fgetc(fp))
/* values for issock */
#define IS_NOT_SOCKET 0
diff --git a/main/internal_functions.c.in b/main/internal_functions.c.in
index f8d840d755..4903d6c4bb 100644
--- a/main/internal_functions.c.in
+++ b/main/internal_functions.c.in
@@ -29,6 +29,12 @@
#include <stdlib.h>
#include <stdio.h>
+#if HAVE_OPENSSL_EXT
+/* zlib typedefs free_func which causes problems if the SSL includes happen
+ * after zlib.h is included */
+# include <openssl/ssl.h>
+#endif
+
@EXT_INCLUDE_CODE@
zend_module_entry *php_builtin_extensions[] = {
diff --git a/main/main.c b/main/main.c
index 4d7d0b7cf3..e6d968dedb 100644
--- a/main/main.c
+++ b/main/main.c
@@ -73,6 +73,7 @@
#include "php_content_types.h"
#include "php_ticks.h"
#include "php_logos.h"
+#include "php_streams.h"
#include "SAPI.h"
/* }}} */
@@ -562,17 +563,24 @@ PHP_FUNCTION(set_time_limit)
*/
static FILE *php_fopen_wrapper_for_zend(const char *filename, char **opened_path)
{
- int issock=0, socketd=0;
- int old_chunk_size;
- FILE *retval;
+ FILE *retval = NULL;
+ php_stream * stream;
TSRMLS_FETCH();
-
- old_chunk_size = php_sock_set_def_chunk_size(1);
- retval=php_fopen_wrapper((char *) filename, "rb", USE_PATH|IGNORE_URL_WIN, &issock, &socketd, opened_path TSRMLS_CC);
- php_sock_set_def_chunk_size(old_chunk_size);
-
- if (issock) {
- retval = fdopen(socketd, "rb");
+
+ stream = php_stream_open_wrapper((char *)filename, "rb", USE_PATH|IGNORE_URL_WIN|REPORT_ERRORS, opened_path TSRMLS_CC);
+ if (stream) {
+ /* no need for us to check the stream type here */
+ php_stream_sock_set_chunk_size(stream, 1);
+
+ if (php_stream_cast(stream, PHP_STREAM_AS_STDIO | PHP_STREAM_CAST_TRY_HARD, (void**)&retval, 1) == SUCCESS) {
+ ZEND_REGISTER_RESOURCE(NULL, stream, php_file_le_stream());
+ }
+ else {
+ php_stream_close(stream);
+ if (opened_path && *opened_path)
+ efree(*opened_path);
+ retval = NULL;
+ }
}
return retval;
}
@@ -941,14 +949,14 @@ int php_module_startup(sapi_module_struct *sf)
REGISTER_INI_ENTRIES();
- /* initialize fopen wrappers registry
- (this uses configuration parameters from php.ini)
+ /* initialize stream wrappers registry
+ * (this uses configuration parameters from php.ini)
*/
- if (php_init_fopen_wrappers(TSRMLS_C) == FAILURE) {
- php_printf("PHP: Unable to initialize fopen url wrappers.\n");
+ if (php_init_stream_wrappers(TSRMLS_C) == FAILURE) {
+ php_printf("PHP: Unable to initialize stream url wrappers.\n");
return FAILURE;
}
-
+
/* initialize registry for images to be used in phpinfo()
(this uses configuration parameters from php.ini)
*/
@@ -1048,7 +1056,9 @@ void php_module_shutdown(TSRMLS_D)
sapi_flush(TSRMLS_C);
zend_shutdown(TSRMLS_C);
- php_shutdown_fopen_wrappers(TSRMLS_C);
+
+ php_shutdown_stream_wrappers(TSRMLS_C);
+
php_shutdown_info_logos();
UNREGISTER_INI_ENTRIES();
diff --git a/main/network.c b/main/network.c
index 6be650875a..1aedbe416a 100644
--- a/main/network.c
+++ b/main/network.c
@@ -17,6 +17,9 @@
*/
/* $Id$ */
+#define PHP_SOCK_CHUNK_SIZE 8192
+#define MAX_CHUNKS_PER_READ 10
+
#include "php.h"
#ifdef PHP_WIN32
@@ -408,6 +411,406 @@ int php_sockaddr_size(php_sockaddr_storage *addr)
}
/* }}} */
+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;
+}
+
+PHPAPI size_t php_stream_sock_set_chunk_size(php_stream * stream, size_t size)
+{
+ size_t oldsize;
+ php_netstream_data_t * sock = (php_netstream_data_t*)stream->abstract;
+
+ if (!php_stream_is(stream, PHP_STREAM_IS_SOCKET))
+ return 0;
+
+ oldsize = sock->chunk_size;
+ sock->chunk_size = size;
+
+ return oldsize;
+}
+
+#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"
+};
+
+
+
+
/*
* Local variables:
* tab-width: 8
diff --git a/main/php_network.h b/main/php_network.h
index b71737265f..b87e709fff 100644
--- a/main/php_network.h
+++ b/main/php_network.h
@@ -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 <netinet/in.h>
#endif
@@ -41,6 +50,10 @@
#include <sys/time.h>
#endif
+#if HAVE_OPENSSL_EXT
+#include <openssl/ssl.h>
+#endif
+
#ifdef HAVE_SOCKADDR_STORAGE
typedef struct sockaddr_storage php_sockaddr_storage;
#else
@@ -56,6 +69,47 @@ PHPAPI int php_connect_nonb(int sockfd, const struct sockaddr *addr, socklen_t a
void php_any_addr(int family, php_sockaddr_storage *addr, unsigned short port);
int php_sockaddr_size(php_sockaddr_storage *addr);
+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;
+
+#define PHP_NETSTREAM_DATA_FROM_STREAM(stream) (php_netstream_data_t*)(stream)->abstract
+
+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);
+/* set the chunk size for the stream; return the old chunk size */
+PHPAPI size_t php_stream_sock_set_chunk_size(php_stream * stream, size_t size);
+
+#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 /* _PHP_NETWORK_H */
/*
diff --git a/main/php_streams.h b/main/php_streams.h
index 6acaafb3fc..39b8e70a46 100755
--- a/main/php_streams.h
+++ b/main/php_streams.h
@@ -19,8 +19,6 @@
#ifndef PHP_STREAMS_H
#define PHP_STREAMS_H
-#if HAVE_PHP_STREAM
-
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
@@ -42,9 +40,23 @@ typedef struct _php_stream_ops {
const char * label; /* label for this ops structure */
} php_stream_ops;
+/* 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);
+typedef void (*php_stream_wrapper_dtor_func_t)(php_stream * stream);
+
+typedef struct _php_stream_wrapper {
+ php_stream_factory_func_t create;
+ php_stream_wrapper_dtor_func_t destroy;
+} php_stream_wrapper;
+
struct _php_stream {
php_stream_ops * ops;
void * abstract; /* convenience pointer for abstraction */
+
+ php_stream_wrapper * wrapper; /* which wrapper was used to open the stream */
+ void * wrapperthis; /* convenience pointer for a instance of a wrapper */
+ zval * wrapperdata; /* fgetwrapperdata retrieves this */
+
int is_persistent;
char mode[16]; /* "rwb" etc. ala stdio */
/* so we know how to clean it up correctly. This should be set to
@@ -68,15 +80,34 @@ PHPAPI int php_stream_seek(php_stream * stream, off_t offset, int whence);
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_putc(php_stream * stream, int c);
PHPAPI int php_stream_flush(php_stream * stream);
PHPAPI char *php_stream_gets(php_stream * stream, char *buf, size_t maxlen);
+PHPAPI int php_stream_puts(php_stream * stream, char * buf);
-/* operations for a stdio FILE; the FILE * must be placed in stream->abstract */
+/* copy up to maxlen bytes from src to dest. If maxlen is 0, copy until eof(src).
+ * Uses mmap if the src is a plain file and at offset 0 */
+PHPAPI size_t php_stream_copy_to_stream(php_stream * src, php_stream * dest, size_t maxlen);
+/* read all data from stream and put into a buffer. Caller must free buffer when done,
+ * according to allocopts.
+ * The copy will use mmap if available. */
+PHPAPI size_t php_stream_read_all(php_stream * src, char ** buf, int persistent);
+
+/* maybe implement someday */
+#define php_stream_error(stream) (0)
+
+/* 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);
+PHPAPI php_stream * php_stream_fopen_tmpfile(void);
+PHPAPI php_stream * php_stream_fopen_temporary_file(const char * dir, const char * pfx, char **opened_path TSRMLS_DC);
/* coerce the stream into some other form */
/* cast as a stdio FILE * */
@@ -86,15 +117,27 @@ PHPAPI php_stream * php_stream_fopen(const char * filename, const char * mode);
/* cast as a socketd */
#define PHP_STREAM_AS_SOCKETD 2
+/* try really, really hard to make sure the cast happens (socketpair) */
+#define PHP_STREAM_CAST_TRY_HARD 0x80000000
+
PHPAPI int php_stream_cast(php_stream * stream, int castas, void ** ret, int show_err);
/* use this to check if a stream can be cast into another form */
#define php_stream_can_cast(stream, as) php_stream_cast(stream, as, NULL, 0)
/* 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 */
+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_wrapper * wrapper TSRMLS_DC);
+PHPAPI int php_unregister_url_stream_wrapper(char * protocol TSRMLS_DC);
-#endif /* HAVE_PHP_STREAM */
+PHPAPI php_stream * php_stream_open_wrapper(char * path, char * mode, int options, char ** opened_path TSRMLS_DC);
#endif
diff --git a/main/streams.c b/main/streams.c
index b79d04a6d4..58e6ba44bb 100755
--- a/main/streams.c
+++ b/main/streams.c
@@ -12,14 +12,28 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Author: Wez Furlong (wez@thebrainroom.com) |
+ | Authors: |
+ | Wez Furlong (wez@thebrainroom.com) |
+ | Borrowed code from: |
+ | Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
+ | Jim Winstead <jimw@php.net> |
+----------------------------------------------------------------------+
*/
#define _GNU_SOURCE
#include "php.h"
+#include "php_globals.h"
+#include "php_network.h"
+#include "php_open_temporary_file.h"
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *) -1)
+#endif
-#if HAVE_PHP_STREAM
#ifdef PHP_WIN32
#define EWOULDBLOCK WSAEWOULDBLOCK
@@ -27,18 +41,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;
@@ -54,11 +60,18 @@ PHPAPI php_stream * php_stream_alloc(php_stream_ops * ops, void * abstract, int
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;
+ php_stream_flush(stream);
+
+ if (stream->wrapper && stream->wrapper->destroy) {
+ stream->wrapper->destroy(stream);
+ }
+
if (call_dtor) {
if (stream->fclose_stdiocast == PHP_STREAM_FCLOSE_FOPENCOOKIE) {
@@ -82,11 +95,17 @@ PHPAPI int php_stream_free(php_stream * stream, int call_dtor)
stream->stdiocast = NULL;
}
}
+
+ if (stream->wrapperdata) {
+ FREE_ZVAL(stream->wrapperdata);
+ }
pefree(stream, stream->is_persistent);
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);
@@ -100,6 +119,14 @@ PHPAPI int php_stream_eof(php_stream * stream)
return stream->ops->read(stream, NULL, 0) == EOF ? 1 : 0;
}
+PHPAPI int php_stream_putc(php_stream * stream, int c)
+{
+ unsigned char buf = c;
+ if (php_stream_write(stream, &buf, 1) > 0)
+ return 1;
+ return EOF;
+}
+
PHPAPI int php_stream_getc(php_stream * stream)
{
char buf;
@@ -109,6 +136,17 @@ PHPAPI int php_stream_getc(php_stream * stream)
return EOF;
}
+PHPAPI int php_stream_puts(php_stream * stream, char * buf)
+{
+ int len;
+ char newline[2] = "\n"; /* is this OK for Win? */
+ len = strlen(buf);
+
+ if (len > 0 && php_stream_write(stream, buf, len) && php_stream_write(stream, newline, 1))
+ return 1;
+ return 0;
+}
+
PHPAPI char *php_stream_gets(php_stream * stream, char *buf, size_t maxlen)
{
@@ -142,18 +180,13 @@ PHPAPI char *php_stream_gets(php_stream * stream, char *buf, size_t maxlen)
PHPAPI int php_stream_flush(php_stream * stream)
{
- return stream->ops->flush(stream);
+ if (stream->ops->flush)
+ return stream->ops->flush(stream);
+ return 0;
}
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);
}
@@ -171,60 +204,310 @@ PHPAPI int php_stream_seek(php_stream * stream, off_t offset, int whence)
if (stream->ops->seek)
return stream->ops->seek(stream, offset, whence);
+ /* emulate forward moving seeks with reads */
+ if (whence == SEEK_CUR && offset > 0) {
+ while(offset-- > 0)
+ if (php_stream_getc(stream) == EOF)
+ return -1;
+ return 0;
+ }
+
zend_error(E_WARNING, "streams of type %s do not support seeking", stream->ops->label);
return -1;
}
-/*------- STDIO stream implementation -------*/
+#define CHUNK_SIZE 8192
+
+PHPAPI size_t php_stream_read_all(php_stream * src, char ** buf, int persistent)
+{
+ size_t ret = 0;
+ char * ptr;
+ size_t len = 0, max_len;
+ int step = CHUNK_SIZE;
+ int min_room = CHUNK_SIZE / 4;
+#if HAVE_MMAP
+ int srcfd;
+#endif
+
+#if HAVE_MMAP
+ /* try and optimize the case where we are copying from the start of a plain file.
+ * We could probably make this work in more situations, but I don't trust the stdio
+ * buffering layer.
+ * */
+ if ( php_stream_is(src, PHP_STREAM_IS_STDIO) &&
+ php_stream_tell(src) == 0 &&
+ SUCCESS == php_stream_cast(src, PHP_STREAM_AS_FD, (void**)&srcfd, 0))
+ {
+ struct stat sbuf;
+
+ if (fstat(srcfd, &sbuf) == 0) {
+ void * srcfile;
+
+ srcfile = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, srcfd, 0);
+ if (srcfile != (void*)MAP_FAILED) {
+
+ *buf = pemalloc(persistent, sbuf.st_size);
+
+ if (*buf) {
+ memcpy(*buf, srcfile, sbuf.st_size);
+ ret = sbuf.st_size;
+ }
+
+ munmap(srcfile, sbuf.st_size);
+ return ret;
+ }
+ }
+ /* fall through - we might be able to copy in smaller chunks */
+ }
+#endif
+
+ ptr = *buf = pemalloc(persistent, step);
+ max_len = step;
+
+ while((ret = php_stream_read(src, ptr, max_len - len))) {
+ len += ret;
+ if (len + min_room >= max_len) {
+ *buf = perealloc(*buf, max_len + step, persistent);
+ max_len += step;
+ ptr = *buf + len;
+ }
+ }
+ if (len) {
+ *buf = perealloc(*buf, len, persistent);
+ }
+ else {
+ pefree(*buf, persistent);
+ *buf = NULL;
+ }
+ return len;
+}
+
+PHPAPI size_t php_stream_copy_to_stream(php_stream * src, php_stream * dest, size_t maxlen)
+{
+ char buf[CHUNK_SIZE];
+ size_t readchunk;
+ size_t haveread = 0;
+ size_t didread;
+#if HAVE_MMAP
+ int srcfd;
+#endif
+
+#if HAVE_MMAP
+ /* try and optimize the case where we are copying from the start of a plain file.
+ * We could probably make this work in more situations, but I don't trust the stdio
+ * buffering layer.
+ * */
+ if ( php_stream_is(src, PHP_STREAM_IS_STDIO) &&
+ php_stream_tell(src) == 0 &&
+ SUCCESS == php_stream_cast(src, PHP_STREAM_AS_FD, (void**)&srcfd, 0))
+ {
+ struct stat sbuf;
+
+ if (fstat(srcfd, &sbuf) == 0) {
+ void * srcfile;
+
+ srcfile = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, srcfd, 0);
+ if (srcfile != (void*)MAP_FAILED) {
+ haveread = php_stream_write(dest, srcfile, sbuf.st_size);
+ munmap(srcfile, sbuf.st_size);
+ return haveread;
+ }
+ }
+ /* fall through - we might be able to copy in smaller chunks */
+ }
+#endif
+
+ while(1) {
+ readchunk = sizeof(buf);
+
+ if (maxlen && (maxlen - haveread) < readchunk)
+ readchunk = maxlen - haveread;
+
+ didread = php_stream_read(src, buf, readchunk);
+ if (didread) {
+ /* extra paranoid */
+ size_t didwrite, towrite;
+ char * writeptr;
+
+ towrite = didread;
+ writeptr = buf;
+ haveread += didread;
+
+ while(towrite) {
+ didwrite = php_stream_write(dest, writeptr, towrite);
+
+ if (didwrite == 0)
+ return 0; /* error */
+
+ towrite -= didwrite;
+ writeptr += didwrite;
+ }
+ }
+ else
+ return 0; /* error */
+
+ if (maxlen - haveread == 0)
+ break;
+ }
+
+ return haveread;
+
+}
+/* }}} */
+
+
+
+/* {{{ ------- 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_temporary_file(const char * dir, const char * pfx, char **opened_path TSRMLS_DC)
+{
+ FILE * fp = php_open_temporary_file(dir, pfx, opened_path);
+
+ if (fp) {
+ php_stream * stream = php_stream_fopen_from_file(fp, "wb");
+ if (stream)
+ return stream;
+ fclose(fp);
+
+ zend_error(E_WARNING, "%s(): unable to allocate stream", get_active_function_name(TSRMLS_C));
+
+ return NULL;
+ }
+ return NULL;
+}
+
+PHPAPI php_stream * php_stream_fopen_tmpfile(void)
+{
+ FILE * fp;
+ php_stream * stream;
+
+ fp = tmpfile();
+ if (fp == NULL) {
+ zend_error(E_WARNING, "tmpfile(): %s", strerror(errno));
+ return NULL;
+ }
+ stream = php_stream_fopen_from_file(fp, "r+");
+ if (stream == NULL) {
+ zend_error(E_WARNING, "tmpfile(): %s", strerror(errno));
+ fclose(fp);
+ return NULL;
+ }
+ return stream;
+}
+
+
+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, data->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);
+ php_stdio_stream_data * data = (php_stdio_stream_data*)stream->abstract;
+
+#if HAVE_FLUSHIO
+ if (data->last_op == 'w')
+ fseek(data->file, 0, SEEK_CUR);
+ data->last_op = 'r';
+#endif
+
+ return fgets(buf, size, data->file);
}
static int php_stdiop_cast(php_stream * stream, int castas, void ** ret)
{
int fd;
+ php_stdio_stream_data * data = (php_stdio_stream_data*)stream->abstract;
switch (castas) {
case PHP_STREAM_AS_STDIO:
if (ret)
- *ret = stream->abstract;
+ *ret = data->file;
return SUCCESS;
case PHP_STREAM_AS_FD:
- fd = fileno((FILE*)stream->abstract);
+ fd = fileno(data->file);
if (fd < 0)
return FAILURE;
if (ret)
@@ -242,21 +525,153 @@ php_stream_ops php_stream_stdio_ops = {
"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) /* {{{ */
+{
+ /* 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 = fopen(filename, mode);
+ 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)
{
@@ -286,9 +701,14 @@ static COOKIE_IO_FUNCTIONS_T stream_cookie_functions =
#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) /* {{{ */
{
+
+ /* trying hard is not yet implemented */
+ castas &= ~PHP_STREAM_CAST_TRY_HARD;
+
if (castas == PHP_STREAM_AS_STDIO) {
if (stream->stdiocast) {
if (ret)
@@ -354,9 +774,110 @@ exit_success:
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;
}
-#endif
+PHPAPI int php_register_url_stream_wrapper(char * protocol, php_stream_wrapper * 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 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_wrapper * 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) {
+ if (FAILURE == zend_hash_find(&url_stream_wrappers_hash, (char*)protocol, n, (void**)&wrapper)) {
+ wrapper = NULL;
+ protocol = NULL;
+ }
+ if (wrapper) {
+ php_stream * stream = wrapper->create(path, mode, options, opened_path TSRMLS_CC);
+ if (stream)
+ stream->wrapper = wrapper;
+ return stream;
+ }
+ }
+
+ 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;
+}
+
+
/*
* Local variables:
* tab-width: 4
diff --git a/tests/strings/003.phpt b/tests/strings/003.phpt
index f7d754988b..97e3aaa38f 100644
--- a/tests/strings/003.phpt
+++ b/tests/strings/003.phpt
@@ -5,9 +5,15 @@ HTML entities
--FILE--
<?php
setlocale (LC_CTYPE, "C");
-echo htmlspecialchars ("<>\"&εΔ\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--
&lt;&gt;&quot;&amp;εΔ
&lt;&gt;&quot;&amp;&aring;&Auml;
+<>"&εΔ
+<>"&εΔ