]> granicus.if.org Git - php/commitdiff
New PHP streams...
authorWez Furlong <wez@php.net>
Fri, 15 Mar 2002 21:03:08 +0000 (21:03 +0000)
committerWez Furlong <wez@php.net>
Fri, 15 Mar 2002 21:03:08 +0000 (21:03 +0000)
41 files changed:
configure.in
ext/curl/curl.c
ext/exif/exif.c
ext/ftp/ftp.c
ext/ftp/ftp.h
ext/ftp/php_ftp.c
ext/gd/gd.c
ext/hyperwave/hw.c
ext/interbase/interbase.c
ext/mailparse/mailparse.c
ext/ming/ming.c
ext/pdf/pdf.c
ext/pgsql/pgsql.c
ext/recode/recode.c
ext/standard/basic_functions.c
ext/standard/exec.c
ext/standard/file.c
ext/standard/file.h
ext/standard/fsock.c
ext/standard/fsock.h
ext/standard/ftp_fopen_wrapper.c
ext/standard/html.c
ext/standard/html.h
ext/standard/http_fopen_wrapper.c
ext/standard/image.c
ext/standard/info.c
ext/standard/php_fopen_wrapper.c
ext/standard/php_fopen_wrappers.h
ext/standard/php_image.h
ext/zlib/php_zlib.h
ext/zlib/zlib.c
ext/zlib/zlib_fopen_wrapper.c
main/fopen_wrappers.c
main/fopen_wrappers.h
main/internal_functions.c.in
main/main.c
main/network.c
main/php_network.h
main/php_streams.h
main/streams.c
tests/strings/003.phpt

index f0cb00d082cbae5b77807fa8e005d147effe099e..a507735cf227235c809967d54bec45a0fdc1ce84 100644 (file)
@@ -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)
index 41f71b0a3a6fa97300118a479412e1a6d8838632..2413d8b4e7cfdfab20482d7394e57ef0935ad137 100644 (file)
@@ -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;
                }
index bce751286216fd5a75b153ffc4b4bf37f7ff8d35..0b10231bea88746bea6482205fcdb6621cd0edc3 100644 (file)
@@ -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
index 3350e8664292be25101de2566091254755ddd608..4121e8dbf3769e92c6827cc63a7f8dce52636dfe 100644 (file)
 #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);
index a44c463461e864837537608b7f36e5886e8fc63f..38b75b1f73364b6a9cf39579203b772bbb1c154d 100644 (file)
@@ -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);
index eb2f8bc4d581c7a22ca17880f6a498c4bc082d78..9d2673360a02e7944baea5323db2a36b889fe36a 100644 (file)
@@ -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;
 }
index 1709c68ade1e4e19b473cfe2c82cb67071f8673f..2bdeb0b6d4d51a9a722c1d8562abcf57b2900d36 100644 (file)
@@ -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;
+
 }
 /* }}} */
 
index 472076389327ab76d4960871db1eb7ed002a66ac..cc2991dab84f116e63b689830bdae088864ce414 100644 (file)
@@ -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 */
index 86dce7501f0490812d9ae918d5b9bd2bc18d8d30..22b2baf7baee16a7e9e0fb1e15a5275eae29b607 100644 (file)
@@ -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;
index 6fed12f1de00e78e9f34621fd3b4faf16af112e1..d3cb0469519a2cc4f003a7d71168079a58b2bce9 100755 (executable)
@@ -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);
index 69bcb57c3a256a5a541fe764a7c21f5cee98f55b..46d0168c46c3b16d10d028d1637d3844ac381b25 100644 (file)
@@ -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);
 
index 5aa6d4394cbd7c66a69b405ad7ac52ee5fcf882d..f283f0ce877d7b38813f0315ae2f2041bf9d17e8 100644 (file)
@@ -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! */
        }
 
index fa96dd254cf8cdbbc2dcc2d3a18878df13773207..35d31bcae5bc2825d3f1d0d02e460547364bcc9a 100644 (file)
@@ -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;
 }
 /* }}} */
index fa1dcd46b8d32080441299e5542687abb842fcb6..488e3b3cfd5144a7365d41546d3aba109df80d93 100644 (file)
@@ -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));
index 8033e577b866213d868251bb1285f73a8d9bff13..89e354891a59bdeb6c6a161e755b2d6c47222ab9 100644 (file)
@@ -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:
index 321a6d94d5ed91e7af84e1887ef7d82196e835b1..34a4cfbaf89b076240065c2dee9528dadf383570 100644 (file)
@@ -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;
index 6e918eb5b12791ae933329a387f6e5258706106d..30cbf8346d0a74c4debd985b7f0b924039f9cf4f 100644 (file)
@@ -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;
index 070eec4a5e839017f5d496180c2b71abea802834..eee46a9de98dd31b6c494d9ddc749c0804ac45f4 100644 (file)
@@ -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
index b1e1314800be8e74e63713b4b3c79f64890cab4d..b672e0087cccc080948e31448a7401322e25c875 100644 (file)
@@ -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;
 }
 /* }}} */
index 13e5c5f1969b30a2a1e219aa1873db4f8e06a8a8..fb134e97bcac5d1259443f524f7e5dcc39286a7d 100644 (file)
 
 #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);
 
index 98552e1143124405abb1826c33d5172d03198a12..4c4b0543b1a679dc110d077eb6dc3707137c8084 100644 (file)
 
 #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;
 }
 /* }}} */
index cc2999ace1c3746676c5d4e5a0276ea548b55b5a..7cf5a25de3e5063cfff42691db61d44a2b516410 100644 (file)
@@ -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;
        }
 }
index ac11acb0f165fbf9b49df08b7ea1e549e725af3e..5f122cbc6e34306c9e1d6a315eefab888bf6f28b 100644 (file)
 #ifndef HTML_H
 #define HTML_H
 
-#define ENT_COMPAT    1
-#define ENT_QUOTES    2
-#define ENT_NOQUOTES  4
+#define ENT_HTML_QUOTE_NONE            0
+#define ENT_HTML_QUOTE_SINGLE  1
+#define ENT_HTML_QUOTE_DOUBLE  2
+
+#define ENT_COMPAT    ENT_HTML_QUOTE_DOUBLE
+#define ENT_QUOTES    (ENT_HTML_QUOTE_DOUBLE | ENT_HTML_QUOTE_SINGLE)
+#define ENT_NOQUOTES  ENT_HTML_QUOTE_NONE
 
 void register_html_constants(INIT_FUNC_ARGS);
 
 PHP_FUNCTION(htmlspecialchars);
 PHP_FUNCTION(htmlentities);
+PHP_FUNCTION(html_entity_decode);
 PHP_FUNCTION(get_html_translation_table);
 
 PHPAPI char *php_escape_html_entities(unsigned char *old, int oldlen, int *newlen, int all, int quote_style, char * hint_charset);
index 24e546bb60f7870670b7889889855a809b51c5af..41ee9d7d54694435e80a374d08ec0cab5096aa5a 100644 (file)
    | 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>
 
 #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
index e0a93f4a97ba6d02b3364e9d5c497f185528c55d..8505078dfce263f5778a30b30e01475fd3a13d0f 100644 (file)
@@ -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:
index 026e00db87f2f6c5d6a0d1a0d51ddf30a5a239f5..ac0d5560e6e6f7c0212629835d061d43d23d41ab 100644 (file)
@@ -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();
 
index 26c9ec2a9ed12b7d3c3d3fbd02c4625ccf809a18..37b3b2b90fd86b4ca96d52d90eda3ffa6b8e9162 100644 (file)
 #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:
index 0cab1fe73e84be814a9fa1ad1aa5fddc705898a1..1cad9777c9aae23fa9d5a4b461c1dd526e157a56 100644 (file)
 #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
index 1837bab6a2c358f9d0bcaedd7bb21afcd42d8e63..3046c8cd62510e289f513c3885e593e0265a446f 100644 (file)
@@ -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 */
index 7a9b0de24733a2af2b3adca3fca9112a606e09e4..bedc65c587a2f1eee58dccb897b8477566b05f08 100644 (file)
@@ -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)
index fdb54ca76e5111541202d5d756a4bfabd66f79b9..1b39fb039902cc34a44234a78d83ebe3af56f22b 100644 (file)
@@ -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);
 }
 /* }}} */
 
index 2ca7aa77f1772e1cae34c3906a70922c8c02b0da..5a59d023ab39b6d8f936b80bd86e52a4b4ac7929 100644 (file)
 #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:
index 7cf55651d4c8618ae1abc3e74c6e897ada3a53a2..9bbd126571b13139c7e1ec794d82b24851b8032b 100644 (file)
 #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)
index dc28af9f471cb4ba3538d8bc400036f706207f53..24e60dcc00ed5aae303a58fa1a61ac582e317518 100644 (file)
 #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
 # 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
index f8d840d7552d26cff4f5451a0982631be3521157..4903d6c4bb052fe5089a6c56d99a441712227182 100644 (file)
 #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[] = {
index 4d7d0b7cf3ef8f5901aea4b5289d7da797ac669a..e6d968dedbe1e0e0556942115f3f549430ad03c7 100644 (file)
@@ -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();
 
index 6be650875a37db2c8465bd20b67926e99888516b..1aedbe416a7a18924254a3be2b18033915cb027b 100644 (file)
@@ -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
index b71737265ff0c360390fe26dfc8d9c2823c88bdf..b87e709fffe3ba983c9adf1836aa051c2fbe5028 100644 (file)
 # 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
 #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 */
 
 /*
index 6acaafb3fcf91c12184bac0e4259bbbb8d7802cc..39b8e70a46f3b0669057b96d7157540d369e1920 100755 (executable)
@@ -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
 
index b79d04a6d485077d4bf0bc7750bdef5a12ea954e..58e6ba44bb71c19ee7e16f34e88f74be5064b683 100755 (executable)
    | 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
 #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
index f7d754988b0603c761877f241cfc96fa02ae2c78..97e3aaa38fc4801886017efbe4fa5c2d2a244a9f 100644 (file)
@@ -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;
+<>"&åÄ
+<>"&åÄ