diff options
| author | Wez Furlong <wez@php.net> | 2003-02-27 17:43:38 +0000 |
|---|---|---|
| committer | Wez Furlong <wez@php.net> | 2003-02-27 17:43:38 +0000 |
| commit | fd61f69077f6156ca71dde60ecfd9ed9765a02db (patch) | |
| tree | 7285ad393cdb5a85107a3329d1ab2bcafe89f051 /ext | |
| parent | 560e33968de93250377606782949f5004affca83 (diff) | |
| download | php-git-fd61f69077f6156ca71dde60ecfd9ed9765a02db.tar.gz | |
Another big commit (tm).
Main Changes:
- Implement a socket transport layer for use by all code that needs to open
some kind of "special" socket for network or IPC.
- Extensions can register (and override) transports.
- Implement ftruncate() on streams via the ioctl-alike option interface.
- Implement mmap() on streams via the ioctl-alike option interface.
- Implement generic crypto API via the ioctl-alike option interface.
(currently only supports OpenSSL, but could support other SSL toolkits,
and other crypto transport protocols).
Impact:
- tcp sockets can be overloaded by the openssl capable sockets at runtime,
removing the link-time requirement for ssl:// and https:// sockets and
streams.
- checking stream types using PHP_STREAM_IS_SOCKET is deprecated, since
there are now a range of possible socket-type streams.
Working towards:
- socket servers using the new transport layer
- mmap support under win32
- Cleaner code.
# I will be updating the win32 build to add the new files shortly
# after this commit.
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/dba/libinifile/inifile.c | 6 | ||||
| -rw-r--r-- | ext/openssl/config.m4 | 2 | ||||
| -rw-r--r-- | ext/openssl/openssl.c | 14 | ||||
| -rw-r--r-- | ext/openssl/php_openssl.h | 2 | ||||
| -rw-r--r-- | ext/openssl/xp_ssl.c | 498 | ||||
| -rw-r--r-- | ext/standard/basic_functions.c | 10 | ||||
| -rw-r--r-- | ext/standard/file.c | 17 | ||||
| -rw-r--r-- | ext/standard/fsock.c | 218 | ||||
| -rw-r--r-- | ext/standard/fsock.h | 4 | ||||
| -rw-r--r-- | ext/standard/ftp_fopen_wrapper.c | 16 | ||||
| -rw-r--r-- | ext/standard/http_fopen_wrapper.c | 29 |
11 files changed, 574 insertions, 242 deletions
diff --git a/ext/dba/libinifile/inifile.c b/ext/dba/libinifile/inifile.c index 2a50c9e884..6e3d94dc4a 100644 --- a/ext/dba/libinifile/inifile.c +++ b/ext/dba/libinifile/inifile.c @@ -87,8 +87,8 @@ inifile * inifile_alloc(php_stream *fp, int readonly, int persistent TSRMLS_DC) int fd = 0; if (!readonly) { - if (php_stream_is(fp, PHP_STREAM_IS_SOCKET)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't truncate sockets"); + if (!php_stream_truncate_supported(fp)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't truncate this stream"); return NULL; } if (SUCCESS != php_stream_cast(fp, PHP_STREAM_AS_FD, (void*)&fd, 1)) { @@ -320,7 +320,7 @@ static int inifile_truncate(inifile *dba, size_t size TSRMLS_DC) { int res; - if ((res=ftruncate(dba->fd, size)) != 0) { + if ((res=php_stream_truncate_set_size(dba->fp, size)) != 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error in ftruncate: %d", res); return FAILURE; } diff --git a/ext/openssl/config.m4 b/ext/openssl/config.m4 index 93c5d052fd..6cc9568428 100644 --- a/ext/openssl/config.m4 +++ b/ext/openssl/config.m4 @@ -3,7 +3,7 @@ dnl $Id$ dnl if test "$PHP_OPENSSL" != "no"; then - PHP_NEW_EXTENSION(openssl, openssl.c, $ext_openssl_shared) + PHP_NEW_EXTENSION(openssl, openssl.c xp_ssl.c, $ext_openssl_shared) OPENSSL_SHARED_LIBADD="-lcrypto -lssl" PHP_SUBST(OPENSSL_SHARED_LIBADD) AC_DEFINE(HAVE_OPENSSL_EXT,1,[ ]) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 976023e329..7fc9da3f5d 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -608,6 +608,13 @@ PHP_MINIT_FUNCTION(openssl) } else { strlcpy(default_ssl_conf_filename, config_filename, sizeof(default_ssl_conf_filename)); } + + php_stream_xport_register("ssl", php_openssl_ssl_socket_factory TSRMLS_CC); + php_stream_xport_register("tls", php_openssl_ssl_socket_factory TSRMLS_CC); + + /* override the default tcp socket provider */ + php_stream_xport_register("tcp", php_openssl_ssl_socket_factory TSRMLS_CC); + return SUCCESS; } /* }}} */ @@ -628,6 +635,13 @@ PHP_MINFO_FUNCTION(openssl) PHP_MSHUTDOWN_FUNCTION(openssl) { EVP_cleanup(); + + php_stream_xport_unregister("ssl" TSRMLS_CC); + php_stream_xport_unregister("tls" TSRMLS_CC); + + /* reinstate the default tcp handler */ + php_stream_xport_register("tcp", php_stream_generic_socket_factory TSRMLS_CC); + return SUCCESS; } /* }}} */ diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h index 89da3167e1..2c7dde6bb6 100644 --- a/ext/openssl/php_openssl.h +++ b/ext/openssl/php_openssl.h @@ -26,6 +26,8 @@ extern zend_module_entry openssl_module_entry; #define phpext_openssl_ptr &openssl_module_entry +php_stream_transport_factory_func php_openssl_ssl_socket_factory; + PHP_MINIT_FUNCTION(openssl); PHP_MSHUTDOWN_FUNCTION(openssl); PHP_MINFO_FUNCTION(openssl); diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c new file mode 100644 index 0000000000..eb449274d9 --- /dev/null +++ b/ext/openssl/xp_ssl.c @@ -0,0 +1,498 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2003 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Wez Furlong <wez@thebrainroom.com> | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#include "php.h" +#include "ext/standard/file.h" +#include "streams/php_streams_int.h" +#include "php_network.h" +#include "php_openssl.h" +#include <openssl/err.h> + + +/* This implementation is very closely tied to the that of the native + * sockets implemented in the core. + * Don't try this technique in other extensions! + * */ + +typedef struct _php_openssl_netstream_data_t { + php_netstream_data_t s; + SSL *ssl_handle; + int enable_on_connect; + int is_client; + int ssl_active; + php_stream_xport_crypt_method_t method; +} php_openssl_netstream_data_t; + +php_stream_ops php_openssl_socket_ops; + +static int handle_ssl_error(php_stream *stream, int nr_bytes TSRMLS_DC) +{ + php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract; + int err = SSL_get_error(sslsock->ssl_handle, nr_bytes); + char esbuf[512]; + char *ebuf = NULL, *wptr = NULL; + size_t ebuf_size = 0; + unsigned long code; + int retry = 1; + + switch(err) { + case SSL_ERROR_ZERO_RETURN: + /* SSL terminated (but socket may still be active) */ + retry = 0; + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* re-negotiation, or perhaps the SSL layer needs more + * packets: retry in next iteration */ + break; + case SSL_ERROR_SYSCALL: + if (ERR_peek_error() == 0) { + if (nr_bytes == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "SSL: fatal protocol error"); + stream->eof = 1; + retry = 0; + } else { + char *estr = php_socket_strerror(php_socket_errno(), NULL, 0); + + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "SSL: %s", estr); + + efree(estr); + retry = 0; + } + break; + } + /* fall through */ + default: + /* some other error */ + while ((code = ERR_get_error()) != 0) { + /* allow room for a NUL and an optional \n */ + if (ebuf) { + esbuf[0] = '\n'; + esbuf[1] = '\0'; + ERR_error_string_n(code, esbuf + 1, sizeof(esbuf) - 2); + } else { + esbuf[0] = '\0'; + ERR_error_string_n(code, esbuf, sizeof(esbuf) - 1); + } + code = strlen(esbuf); + esbuf[code] = '\0'; + + ebuf = erealloc(ebuf, ebuf_size + code + 1); + if (wptr == NULL) { + wptr = ebuf; + } + + /* also copies the NUL */ + memcpy(wptr, esbuf, code + 1); + wptr += code; + } + + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "SSL operation failed with code %d.%s%s", + err, + ebuf ? "OpenSSL Error messages:\n" : "", + ebuf ? ebuf : ""); + + retry = 0; + } + return retry; +} + + +static size_t php_openssl_sockop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) +{ + php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract; + size_t didwrite; + + if (sslsock->ssl_active) { + int retry = 1; + + do { + didwrite = SSL_write(sslsock->ssl_handle, buf, count); + + if (didwrite <= 0) { + retry = handle_ssl_error(stream, didwrite TSRMLS_CC); + } else { + break; + } + } while(retry); + + } else { + didwrite = php_stream_socket_ops.write(stream, buf, count TSRMLS_CC); + } + + if (didwrite > 0) + php_stream_notify_progress_increment(stream->context, didwrite, 0); + + return didwrite; +} + +static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) +{ + php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract; + int nr_bytes = 0; + + if (sslsock->ssl_active) { + int retry = 1; + + do { + nr_bytes = SSL_read(sslsock->ssl_handle, buf, count); + + if (nr_bytes <= 0) { + retry = handle_ssl_error(stream, nr_bytes TSRMLS_CC); + if (retry == 0 && !SSL_pending(sslsock->ssl_handle)) { + stream->eof = 1; + } + } else { + /* we got the data */ + break; + } + } while (retry); + } + else + { + nr_bytes = php_stream_socket_ops.read(stream, buf, count TSRMLS_CC); + } + + if (nr_bytes > 0) + php_stream_notify_progress_increment(stream->context, nr_bytes, 0); + + return nr_bytes; +} + + +static int php_openssl_sockop_close(php_stream *stream, int close_handle TSRMLS_DC) +{ + php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract; + fd_set wrfds, efds; + int n; + struct timeval timeout; + + if (close_handle) { + if (sslsock->ssl_active) { + SSL_shutdown(sslsock->ssl_handle); + sslsock->ssl_active = 0; + } + if (sslsock->ssl_handle) { + SSL_free(sslsock->ssl_handle); + sslsock->ssl_handle = NULL; + } + if (sslsock->s.socket != -1) { + /* prevent more data from coming in */ + shutdown(sslsock->s.socket, SHUT_RD); + + /* try to make sure that the OS sends all data before we close the connection. + * Essentially, we are waiting for the socket to become writeable, which means + * that all pending data has been sent. + * We use a small timeout which should encourage the OS to send the data, + * but at the same time avoid hanging indefintely. + * */ + do { + FD_ZERO(&wrfds); + FD_SET(sslsock->s.socket, &wrfds); + efds = wrfds; + + timeout.tv_sec = 0; + timeout.tv_usec = 5000; /* arbitrary */ + + n = select(sslsock->s.socket + 1, NULL, &wrfds, &efds, &timeout); + } while (n == -1 && php_socket_errno() == EINTR); + + closesocket(sslsock->s.socket); + sslsock->s.socket = -1; + } + } + + pefree(sslsock, php_stream_is_persistent(stream)); + + return 0; +} + +static int php_openssl_sockop_flush(php_stream *stream TSRMLS_DC) +{ + return php_stream_socket_ops.flush(stream TSRMLS_CC); +} + +static int php_openssl_sockop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) +{ + return php_stream_socket_ops.stat(stream, ssb TSRMLS_CC); +} + +static inline int php_openssl_setup_crypto(php_stream *stream, + php_openssl_netstream_data_t *sslsock, + php_stream_xport_crypto_param *cparam + TSRMLS_DC) +{ + SSL_CTX *ctx; + SSL_METHOD *method; + + if (sslsock->ssl_handle) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL/TLS already set-up for this stream"); + return -1; + } + + /* need to do slightly different things, based on client/server method, + * so lets remember which method was selected */ + + switch (cparam->inputs.method) { + case STREAM_CRYPTO_METHOD_SSLv23_CLIENT: + sslsock->is_client = 1; + method = SSLv23_client_method(); + break; + case STREAM_CRYPTO_METHOD_SSLv2_CLIENT: + sslsock->is_client = 1; + method = SSLv2_client_method(); + break; + case STREAM_CRYPTO_METHOD_SSLv3_CLIENT: + sslsock->is_client = 1; + method = SSLv3_client_method(); + break; + case STREAM_CRYPTO_METHOD_TLS_CLIENT: + sslsock->is_client = 1; + method = TLSv1_client_method(); + break; + case STREAM_CRYPTO_METHOD_SSLv23_SERVER: + sslsock->is_client = 0; + method = SSLv23_server_method(); + break; + case STREAM_CRYPTO_METHOD_SSLv3_SERVER: + sslsock->is_client = 0; + method = SSLv3_server_method(); + break; + case STREAM_CRYPTO_METHOD_SSLv2_SERVER: + sslsock->is_client = 0; + method = SSLv2_server_method(); + break; + case STREAM_CRYPTO_METHOD_TLS_SERVER: + sslsock->is_client = 0; + method = TLSv1_server_method(); + break; + default: + printf("unknown method\n"); + return -1; + + } + + ctx = SSL_CTX_new(method); + if (ctx == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create an SSL context"); + return -1; + } + + sslsock->ssl_handle = SSL_new(ctx); + if (sslsock->ssl_handle == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create an SSL handle"); + SSL_CTX_free(ctx); + return -1; + } + + if (!SSL_set_fd(sslsock->ssl_handle, sslsock->s.socket)) { + printf("failed to set fd %d\n", sslsock->s.socket); + handle_ssl_error(stream, 0 TSRMLS_CC); + } + + if (cparam->inputs.session) { + printf("sess=%p\n", cparam->inputs.session); + if (cparam->inputs.session->ops != &php_openssl_socket_ops) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied session stream must be an SSL enabled stream"); + } else { + SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle); + } + } +printf("crypto prepared for fd=%d\n", sslsock->s.socket); + return 0; +} + +static inline int php_openssl_enable_crypto(php_stream *stream, + php_openssl_netstream_data_t *sslsock, + php_stream_xport_crypto_param *cparam + TSRMLS_DC) +{ + int n, retry = 1; + + if (cparam->inputs.activate) { + if (sslsock->is_client) { + do { + n = SSL_connect(sslsock->ssl_handle); + + if (n <= 0) { + retry = handle_ssl_error(stream, n TSRMLS_CC); + printf("error; retry = %d\n", retry); + } else { + break; + } + } while (retry); + + printf("enabled_crypto: n=%d\n", n); + if (n == 1) { + sslsock->ssl_active = 1; + } + + return n; + + } else { + + } + } else { + /* deactivate - common for server/client */ + } + return -1; +} + +static int php_openssl_sockop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) +{ + php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract; + php_stream_xport_crypto_param *cparam = (php_stream_xport_crypto_param *)ptrparam; + php_stream_xport_param *xparam = (php_stream_xport_param *)ptrparam; + + switch (option) { + case PHP_STREAM_OPTION_CRYPTO_API: + + switch(cparam->op) { + + case STREAM_XPORT_CRYPTO_OP_SETUP: + cparam->outputs.returncode = php_openssl_setup_crypto(stream, sslsock, cparam TSRMLS_CC); + return PHP_STREAM_OPTION_RETURN_OK; + case STREAM_XPORT_CRYPTO_OP_ENABLE: + cparam->outputs.returncode = php_openssl_enable_crypto(stream, sslsock, cparam TSRMLS_CC); + return PHP_STREAM_OPTION_RETURN_OK; + default: + /* fall through */ + } + + break; + + case PHP_STREAM_OPTION_XPORT_API: + switch(xparam->op) { + + case STREAM_XPORT_OP_CONNECT: + case STREAM_XPORT_OP_CONNECT_ASYNC: + /* TODO: Async connects need to check the enable_on_connect option when + * we notice that the connect has actually been established */ + php_stream_socket_ops.set_option(stream, option, value, ptrparam TSRMLS_CC); + + if (xparam->outputs.returncode == 0 && sslsock->enable_on_connect) { + if (php_stream_xport_crypto_setup(stream, sslsock->method, NULL TSRMLS_CC) < 0 || + php_stream_xport_crypto_enable(stream, 1 TSRMLS_CC) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to enable crypto"); + xparam->outputs.returncode = -1; + } + } + return PHP_STREAM_OPTION_RETURN_OK; + default: + /* fall through */ + } + } + + return php_stream_socket_ops.set_option(stream, option, value, ptrparam TSRMLS_CC); +} + +static int php_openssl_sockop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC) +{ + php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract; + + switch(castas) { + case PHP_STREAM_AS_STDIO: + if (sslsock->ssl_active) { + return FAILURE; + } + if (ret) { + *ret = fdopen(sslsock->s.socket, stream->mode); + if (*ret) { + return SUCCESS; + } + return FAILURE; + } + return SUCCESS; + case PHP_STREAM_AS_FD: + case PHP_STREAM_AS_SOCKETD: + if (sslsock->ssl_active) { + return FAILURE; + } + if (ret) { + *ret = (void*)sslsock->s.socket; + } + return SUCCESS; + default: + return FAILURE; + } +} + +php_stream_ops php_openssl_socket_ops = { + php_openssl_sockop_write, php_openssl_sockop_read, + php_openssl_sockop_close, php_openssl_sockop_flush, + "tcp_socket/ssl", + NULL, /* seek */ + php_openssl_sockop_cast, + php_openssl_sockop_stat, + php_openssl_sockop_set_option, +}; + + +PHPAPI php_stream *php_openssl_ssl_socket_factory(const char *proto, long protolen, + char *resourcename, long resourcenamelen, + const char *persistent_id, int options, int flags, + struct timeval *timeout, + php_stream_context *context STREAMS_DC TSRMLS_DC) +{ + php_stream *stream = NULL; + php_openssl_netstream_data_t *sslsock = NULL; + + sslsock = pemalloc(sizeof(php_openssl_netstream_data_t), persistent_id ? 1 : 0); + memset(sslsock, 0, sizeof(php_openssl_netstream_data_t)); + + sslsock->s.is_blocked = 1; + sslsock->s.timeout.tv_sec = FG(default_socket_timeout); + sslsock->s.timeout.tv_usec = 0; + + /* we don't know the socket until we have determined if we are binding or + * connecting */ + sslsock->s.socket = -1; + + stream = php_stream_alloc_rel(&php_openssl_socket_ops, sslsock, persistent_id, "r+"); + + if (stream == NULL) { + pefree(sslsock, persistent_id ? 1 : 0); + return NULL; + } + + if (strncmp(proto, "ssl", protolen) == 0) { + sslsock->enable_on_connect = 1; + sslsock->method = STREAM_CRYPTO_METHOD_SSLv23_CLIENT; + } else if (strncmp(proto, "tls", protolen) == 0) { + sslsock->enable_on_connect = 1; + sslsock->method = STREAM_CRYPTO_METHOD_TLS_CLIENT; + } + + return stream; +} + + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 9a14905b3a..84c1347f50 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1166,9 +1166,6 @@ PHP_RINIT_FUNCTION(basic) BG(locale_string) = NULL; BG(user_compare_func_name) = NULL; BG(array_walk_func_name) = NULL; -#ifdef HAVE_MMAP - BG(mmap_file) = NULL; -#endif BG(page_uid) = -1; BG(page_gid) = -1; BG(page_inode) = -1; @@ -1219,7 +1216,6 @@ PHP_RSHUTDOWN_FUNCTION(basic) } STR_FREE(BG(locale_string)); - PHP_RSHUTDOWN(fsock)(SHUTDOWN_FUNC_ARGS_PASSTHRU); PHP_RSHUTDOWN(filestat)(SHUTDOWN_FUNC_ARGS_PASSTHRU); #ifdef HAVE_SYSLOG_H PHP_RSHUTDOWN(syslog)(SHUTDOWN_FUNC_ARGS_PASSTHRU); @@ -1246,12 +1242,6 @@ PHP_RSHUTDOWN_FUNCTION(basic) BG(user_filter_map) = NULL; } -#ifdef HAVE_MMAP - if (BG(mmap_file)) { - munmap(BG(mmap_file), BG(mmap_len)); - } -#endif - return SUCCESS; } diff --git a/ext/standard/file.c b/ext/standard/file.c index 0674f4b3fd..9da076e08a 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -647,6 +647,7 @@ PHP_FUNCTION(stream_get_meta_data) add_assoc_long(return_value, "unread_bytes", stream->writepos - stream->readpos); +#if 0 if (php_stream_is(stream, PHP_STREAM_IS_SOCKET)) { php_netstream_data_t *sock = PHP_NETSTREAM_DATA_FROM_STREAM(stream); @@ -654,10 +655,13 @@ PHP_FUNCTION(stream_get_meta_data) add_assoc_bool(return_value, "blocked", sock->is_blocked); add_assoc_bool(return_value, "eof", stream->eof); } else { +#endif add_assoc_bool(return_value, "timed_out", 0); add_assoc_bool(return_value, "blocked", 1); add_assoc_bool(return_value, "eof", php_stream_eof(stream)); +#if 0 } +#endif } /* }}} */ @@ -2237,7 +2241,7 @@ PHP_FUNCTION(unlink) } /* }}} */ -/* {{{ proto int ftruncate(resource fp, int size) +/* {{{ proto bool ftruncate(resource fp, int size) Truncate file to 'size' length */ PHP_NAMED_FUNCTION(php_if_ftruncate) { @@ -2254,15 +2258,12 @@ PHP_NAMED_FUNCTION(php_if_ftruncate) convert_to_long_ex(size); - if (php_stream_is(stream, PHP_STREAM_IS_SOCKET)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't truncate sockets!"); + if (!php_stream_truncate_supported(stream)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't truncate this stream!"); RETURN_FALSE; } - if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&fd, 1)) { - ret = ftruncate(fd, Z_LVAL_PP(size)); - RETURN_LONG(ret + 1); - } - RETURN_FALSE; + + RETURN_BOOL(0 == php_stream_truncate_set_size(stream, Z_LVAL_PP(size))); } /* }}} */ diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c index bbe6d7debb..8f41cf4d3f 100644 --- a/ext/standard/fsock.c +++ b/ext/standard/fsock.c @@ -20,122 +20,19 @@ /* $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] */ - #include "php.h" #include "php_globals.h" #include <stdlib.h> #include <stddef.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#ifdef HAVE_FCNTL_H -# include <fcntl.h> -#endif - -#ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -#endif - -#include <sys/types.h> -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#ifdef PHP_WIN32 -#include <winsock2.h> -#elif defined(NETWARE) -#ifdef NEW_LIBC -#ifdef USE_WINSOCK -#include <novsock2.h> -#else -#include <netinet/in.h> -#include <netdb.h> -/*#include <sys/socket.h>*/ -#include <sys/select.h> -/*#else -#include <sys/socket.h>*/ -#endif -#endif -#else -#include <netinet/in.h> -#include <netdb.h> -#if HAVE_ARPA_INET_H -#include <arpa/inet.h> -#endif -#endif -#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE) -#undef AF_UNIX -#endif -#if defined(AF_UNIX) -#include <sys/un.h> -#endif -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif - -#ifndef PF_INET -#define PF_INET AF_INET -#endif - -#ifndef PF_UNIX -#define PF_UNIX AF_UNIX -#endif - -#include <string.h> -#include <errno.h> - -#include "base64.h" -#include "file.h" -#include "url.h" -#include "fsock.h" - #include "php_network.h" - -#ifdef ZTS -static int fsock_globals_id; -#endif - -#ifdef PHP_WIN32 -#define EWOULDBLOCK WSAEWOULDBLOCK -#elif defined(NETWARE) -#ifdef USE_WINSOCK -#define EWOULDBLOCK WSAEWOULDBLOCK -#endif -#endif - -/* {{{ php_lookup_hostname */ - -/* - * Converts a host name to an IP address. - * TODO: This looks like unused code suitable for nuking. - */ -PHPAPI int php_lookup_hostname(const char *addr, struct in_addr *in) -{ - struct hostent *host_info; - - if (!inet_aton(addr, in)) { - /* XXX NOT THREAD SAFE */ - host_info = gethostbyname(addr); - if (host_info == 0) { - /* Error: unknown host */ - return -1; - } - *in = *((struct in_addr *) host_info->h_addr); - } - return 0; -} -/* }}} */ +#include "file.h" /* {{{ php_fsockopen() */ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent) { char *host; - int host_len; + long host_len; int port = -1; zval *zerrno = NULL, *zerrstr = NULL; double timeout = FG(default_socket_timeout); @@ -144,6 +41,9 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent) char *hashkey = NULL; php_stream *stream = NULL; int err; + char *hostname = NULL; + long hostname_len; + char *errstr = NULL; RETVAL_FALSE; @@ -151,22 +51,17 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent) RETURN_FALSE; } - if (persistent) { spprintf(&hashkey, 0, "pfsockopen__%s:%d", host, port); - - switch(php_stream_from_persistent_id(hashkey, &stream TSRMLS_CC)) { - case PHP_STREAM_PERSISTENT_SUCCESS: - /* TODO: could check if the socket is still alive here */ - php_stream_to_zval(stream, return_value); - - /* fall through */ - case PHP_STREAM_PERSISTENT_FAILURE: - efree(hashkey); - return; - } } + if (port > 0) { + hostname_len = spprintf(&hostname, 0, "%s:%d", host, port); + } else { + hostname_len = host_len; + hostname = host; + } + /* prepare the timeout value for use */ conv = (unsigned long) (timeout * 1000000.0); tv.tv_sec = conv / 1000000; @@ -181,88 +76,29 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent) ZVAL_STRING(zerrstr, "", 1); } - if (port > 0) { /* connect to a host */ - enum php_sslflags_t { php_ssl_none, php_ssl_v23, php_ssl_tls }; - enum php_sslflags_t ssl_flags = php_ssl_none; - struct { - char *proto; - int protolen; - int socktype; - enum php_sslflags_t ssl_flags; - /* more flags to be added here */ - } sockmodes[] = { - { "udp://", 6, SOCK_DGRAM, php_ssl_none }, - { "tcp://", 6, SOCK_STREAM, php_ssl_none }, - { "ssl://", 6, SOCK_STREAM, php_ssl_v23 }, - { "tls://", 6, SOCK_STREAM, php_ssl_tls }, - /* more modes to be added here */ - { NULL, 0, 0 } - }; - int socktype = SOCK_STREAM; - int i; - - for (i = 0; sockmodes[i].proto != NULL; i++) { - if (strncmp(host, sockmodes[i].proto, sockmodes[i].protolen) == 0) { - ssl_flags = sockmodes[i].ssl_flags; - socktype = sockmodes[i].socktype; - host += sockmodes[i].protolen; - break; - } - } -#if !HAVE_OPENSSL_EXT - if (ssl_flags != php_ssl_none) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "no SSL support in this build"); - } - else -#endif - stream = php_stream_sock_open_host(host, (unsigned short)port, socktype, &tv, hashkey); - - /* Preserve error */ - err = php_socket_errno(); + stream = php_stream_xport_create(hostname, hostname_len, ENFORCE_SAFE_MODE | REPORT_ERRORS, + STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, hashkey, &tv, NULL, &errstr, &err); - if (stream == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to connect to %s:%d", host, port); - } - -#if HAVE_OPENSSL_EXT - if (stream && ssl_flags != php_ssl_none) { - 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(), NULL TSRMLS_CC); - break; - case php_ssl_tls: - ssl_ret = php_stream_sock_ssl_activate_with_method(stream, 1, TLSv1_client_method(), NULL TSRMLS_CC); - break; - default: - /* unknown ?? */ - break; - } - if (ssl_ret == FAILURE) - php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to activate SSL mode %d", ssl_flags); - } -#endif - - } else { - /* FIXME: Win32 - this probably does not return sensible errno and errstr */ - stream = php_stream_sock_open_unix(host, host_len, hashkey, &tv); - err = php_socket_errno(); + if (port > 0) { + efree(hostname); + } + if (stream == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to connect to %s:%d", host, port); } - if (hashkey) + if (hashkey) { efree(hashkey); + } if (stream == NULL) { if (zerrno) { zval_dtor(zerrno); ZVAL_LONG(zerrno, err); } - if (zerrstr) { - char *buf = php_socket_strerror(err, NULL, 0); - - /* no need to dup; we would only need to efree buf anyway */ + if (zerrstr && errstr) { + /* no need to dup; we need to efree buf anyway */ zval_dtor(zerrstr); - ZVAL_STRING(zerrstr, buf, 0); + ZVAL_STRING(zerrstr, errstr, 0); } RETURN_FALSE; } @@ -287,12 +123,6 @@ PHP_FUNCTION(pfsockopen) } /* }}} */ -/* {{{ RSHUTDOWN_FUNCTION(fsock) */ -PHP_RSHUTDOWN_FUNCTION(fsock) -{ - return SUCCESS; -} -/* }}} */ /* * Local variables: * tab-width: 4 diff --git a/ext/standard/fsock.h b/ext/standard/fsock.h index 966fc1ecec..7d263c31e1 100644 --- a/ext/standard/fsock.h +++ b/ext/standard/fsock.h @@ -40,10 +40,6 @@ PHP_FUNCTION(fsockopen); PHP_FUNCTION(pfsockopen); -PHPAPI int php_lookup_hostname(const char *addr, struct in_addr *in); - -PHP_RSHUTDOWN_FUNCTION(fsock); - /* * Local variables: * tab-width: 4 diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index 98b5a27892..192786058d 100644 --- a/ext/standard/ftp_fopen_wrapper.c +++ b/ext/standard/ftp_fopen_wrapper.c @@ -142,10 +142,8 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch char *scratch; int result; int i, use_ssl; -#if HAVE_OPENSSL_EXT int use_ssl_on_data=0; php_stream *reuseid=NULL; -#endif char *tpath, *ttpath, *hoststart=NULL; size_t file_size = 0; @@ -182,7 +180,6 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch goto errexit; } -#if HAVE_OPENSSL_EXT if (use_ssl) { /* send the AUTH TLS request name */ @@ -212,7 +209,9 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch } if (use_ssl) { - if (use_ssl && php_stream_sock_ssl_activate(stream, 1) == FAILURE) { + if (php_stream_xport_crypto_setup(stream, + STREAM_CRYPTO_METHOD_SSLv23_CLIENT, NULL TSRMLS_CC) < 0 + || php_stream_xport_crypto_enable(stream, 1 TSRMLS_CC) < 0) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to activate SSL mode"); php_stream_close(stream); stream = NULL; @@ -240,8 +239,6 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch #endif } -#endif - /* send the user name */ php_stream_write_string(stream, "USER "); if (resource->user != NULL) { @@ -433,14 +430,15 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch php_stream_context_set(datastream, context); php_stream_notify_progress_init(context, 0, file_size); -#if HAVE_OPENSSL_EXT - if (use_ssl_on_data && php_stream_sock_ssl_activate_with_method(datastream, 1, SSLv23_method(), reuseid TSRMLS_CC) == FAILURE) { + if (use_ssl_on_data && (php_stream_xport_crypto_setup(stream, + STREAM_CRYPTO_METHOD_SSLv23_CLIENT, NULL TSRMLS_CC) < 0 || + php_stream_xport_crypto_enable(stream, 1 TSRMLS_CC) < 0)) { + php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to activate SSL mode"); php_stream_close(datastream); datastream = NULL; goto errexit; } -#endif /* remember control stream */ datastream->wrapperdata = (zval *)stream; diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index e6da657882..dbe7340a9a 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -99,6 +99,8 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch char tmp_line[128]; size_t chunk_size = 0, file_size = 0; int eol_detect; + char *transport_string, *errstr = NULL; + int transport_len; if (strpbrk(mode, "awx+")) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "HTTP wrapper does not support writeable connections."); @@ -110,14 +112,26 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch return NULL; use_ssl = resource->scheme && (strlen(resource->scheme) > 4) && 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, NULL, 0); + transport_len = spprintf(&transport_string, 0, "%s://%s:%d", use_ssl ? "ssl" : "tcp", resource->host, resource->port); + + stream = php_stream_xport_create(transport_string, transport_len, options, + STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, + NULL, NULL, context, &errstr, NULL); + + if (errstr) { + php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "%s", errstr); + efree(errstr); + errstr = NULL; + } + + efree(transport_string); + if (stream == NULL) goto out; @@ -133,17 +147,6 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch php_stream_context_set(stream, context); php_stream_notify_info(context, PHP_STREAM_NOTIFY_CONNECT, NULL, 0); - -#if HAVE_OPENSSL_EXT - if (use_ssl) { - if (php_stream_sock_ssl_activate(stream, 1) == FAILURE) { - php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to activate SSL mode"); - php_stream_close(stream); - stream = NULL; - goto out; - } - } -#endif scratch_len = strlen(path) + 32; scratch = emalloc(scratch_len); |
